/* ======================================================================== *
       			  screen.c - Main Module for CDTV Welcome Disk
							       By Talin.
				  Compiled under Manx 5.0 with small code/data
 * ======================================================================== */

#if 0

	problems remaining:
		3. Blanking area color incorrect 2nd pass.
		5. Need to adjust display position using preferences
		9. adjust the case of all the file names.
		20. Redo audio panel tutrorial.
		21. Redo preferences tutorial.
		50. Show digitized picture of unit before tutorial at start of
				"Basic operations".
		51. Add green highlight around earth / main menu...
#endif

#include "welcome.h"

	/* Play-X subroutines */

BOOL LoadPlayXSong(char *,long);
WORD PlayNote(UWORD channel,UWORD note,UWORD dur);
void PlaySong(WORD which);
void LoopSong(WORD which);
void AdvanceSong(WORD which);
void SetVolume(WORD vol);

	/* macros for dealing with custom registers */

#define CUSTREGS		((struct Custom *)0x00dff000)
#define	DISPLAY_ON		(CUSTREGS->dmacon = BITSET|DMAF_RASTER)
#define	DISPLAY_OFF		(CUSTREGS->dmacon = BITCLR|DMAF_RASTER)

	/* used to prevent dropping of sprites (might not be needed) */

/* #define MIN_VIEW_DX		128 */
#define MIN_VIEW_DX		64

#define	OSCAN_WIDTH		352
#define OSCAN_HEIGHT	272
#define	OSCAN_MODULO	(OSCAN_WIDTH/8)			/* = 44							*/

#define NTSC_HEIGHT		232

#define STD_WIDTH		320
#define STD_HEIGHT		200
#define STD_MODULO		(STD_WIDTH/8)			/* = 40							*/

#define LORES_COLORS	32
#define LORES_DEPTH		5
#define EHB_DEPTH		6

#define SCREEN_WIDTH	320

#define PAGE_HEIGHT		108
#define RAST_HEIGHT		116 /* extra lines added for horizontal fiddling */
#define TEXT_HEIGHT		92

#define MENU_WIDTH		320
#define MENU_HEIGHT		200
#define MENU_DEPTH		4
#define MENU_COLORS		(1 << (MENU_DEPTH+1))

#define BINKSOUND		"data/bink"
#define BELLSOUND		"data/bell"

#define INTROTHEME		"data/theme1.mxp"
#define GLOBESTARS		"data/GlobeStars.oscan"

#define HANDS1			"data/Hands.01.Br"
#define OCEAN1			"data/Ocean.oscan"
#define SNOW1			"data/TVSnow.oscan"
#define CDFIN			"data/CDFinFin4"
#define TUTOR_MENU		"data/TutorialMenu.Pic"
#define MAIN_MENU		"data/MainMenu.Pic"

#define STONE1			"data/StoneLt.br"
#define STONE2			"data/StoneMd.br"
#define STONE3			"data/StoneDk.br"
#define BEVEL			"data/BevelMask.br"

struct TextAttr
	topaz_8 = { (UBYTE *)"topaz.font",8,FS_NORMAL ,FPF_ROMFONT };

struct Process			*myprocess=NULL;		/* pointer to Discovery task	*/
APTR					oldWindowPtr=NULL;		/* original window pointer		*/

struct UCopList			*ucl;					/* pointer to user copper list	*/

WORD					xoffset,				/* x offset for MOREROWS support */
						yoffset,				/* y offset for PAL support		*/
						yadjust;				/* DyOffset adjust for PAL		*/

struct View				v,						/* the main view for the game	*/
						v_null,					/* empty view					*/
						v_roll1,				/* view 1 for roller coaster	*/
						v_roll2,				/* view 2 for roller coaster	*/
						*myView,				/* the current view				*/
						*oldview;				/* previous workbench view		*/

struct ViewPort			vp_main,				/* ViewPort for the title screen */
						vp_null,				/* empty ViewPort				*/
						*vport;

struct RasInfo			ri_page1,				/* RasInfo for page 1 vport		*/
						ri_page2,				/* RasInfo for page 2 vport		*/
						ri_pic,					/* RasInfo for picture viewing	*/
						ri_title,				/* RasInfo for title vport		*/
						ri_null,				/* empty RasInfo				*/
						ri_roller,				/* used in roller coaster scene	*/
						ri_track;				/* as above...					*/

struct fpage			fp_page1,				/* first flip-page struct		*/
						fp_page2,				/* second flip-page struct		*/
						*fp_drawing,			/* buffer we are drawing on		*/
						*fp_viewing;			/* buffer we are viewing.		*/

PLANEPTR				title_credits;

static struct BitMap 	bm_main,
						bm_first,
						bm_second,
						*bm_draw;

struct BitMap			bm_null;				/* null BitMap					*/

struct RastPort			rp_text,				/* rastport for drawing questions */
						rp_slab;				/* for temporary drawing...		*/

UWORD					colors[32];

#define	BM_SIZE			(sizeof (struct BitMap))

PLANEPTR				*pl;
LONG					i;
SHORT					j,k,n;

struct GfxBase			*GfxBase=NULL;
struct IntuitionBase	*IntuitionBase=NULL;
struct Library			*TranslatorBase=NULL;
extern struct ExecBase	*SysBase;

struct TextFont			*TopazFont;
/* extern struct TextFont	CarnelianFont; */

#define titlecolors		pagecolors

USHORT pagecolors [] = {
	0x000,0xFFF,0xF00,0x520,0x410,0x940,0xA30,0xF63,
	0xFA0,0x0DD,0x0AF,0x05E,0x00D,0x008,0xF0F,0xD65,
	0x620,0xC85,0x953,0xFCA,0x333,0x444,0x15A,0x666,
	0x0A0,0x889,0x060,0xFF0,0xBBC,0x900,0x0D0,0x080 };

USHORT textcolors [] = { 0x000, 0xf00, 0xff0, 0xf0f };

USHORT endcolors [] = {
	0x000,0x000,0x004,0x008,0x00B,0x00F,0x88F,0xFFF,
	0x000,0xBA7,0x542,0x875,0x000,0x443,0x221,0x332 };

USHORT mi_colors[32];

USHORT mi_fade[2][5] = {
	{ 0x0bbd, 0x0bbd, 0x0cce, 0x0cce, 0x0ddf },
	{ 0x099b, 0x088a, 0x0779, 0x0668, 0x0557 } };

char					actor_num,				/* actor number for this came	*/
						*actor_name;			/* the filename for the actor	*/

WORD					skipped = FALSE;		/* user_skip flag.				*/

#define SKIPPED			skipped

signed char				xjoy,					/* joystick x position			*/
						yjoy;					/* joystick y position			*/
/*BYTE					button;					/* joystick button				*/

#define LT_HIT_OFFSET	2
#define RT_HIT_OFFSET	18

	/* Used by the input handler */

struct	in_work			handler_data;
WORD					numreq = 0;
WORD					stopgame = 0;
WORD					closedwb = 0;

	/* Used by vblank interrupt */

extern void VBlankInterface();					/* declare vblank function */

struct Interrupt VertBlank =
{	NULL,NULL,-60,NT_INTERRUPT,"Welcome",		/* node, pri = -60 */
	NULL,										/* data ptr, same as inputevent */
	VBlankInterface								/* code ptr */
};

extern struct ColorAnimation *color_list;

extern UWORD			playflag;
extern LONG				lastcamg;

LOCK					olddir=NULL;

/* UWORD					*mtextData; */

void					*bink_sample,
						*bell_sample;

void					*voice_sample,
						*async_sample,
						*channel_sample;

int						error;

char					flipper;

char					inhibit = 0,
						looping;

#define PLAY_MUSIC		TRUE

	/* definitions for transitions */

#define TRANSITION_MAX	0x10000
#define TRANSITION_HIGH(i)		(TRANSITION_MAX + TRANSITION_MAX/(i*2))
#define TRANSITION_STEPS(i)		(TRANSITION_MAX/i)

enum section_numbers {
	GLOBE_SECTION=0,
	SNOW_SECTION,
	NATIONPICS_SECTION,
	ROLLER_SECTION
};


struct Selector;

	/* from IFFSubs.c */

struct IFFPic *GetPicture(char *filename, UWORD *colors, UWORD maxcolors, struct MinList *track);
/* struct IFFPic *CatGetPicture(UWORD *colors, UWORD maxcolors, struct MinList *track); */
struct IFFPic *MakePicture(int width, int height, int depth, struct MinList *track);
struct IFFPic *MakeMask(struct IFFPic *source, struct MinList *track);
/* BOOL SavePic(char *filename, struct BitMap *bm, UWORD *palette, WORD count); */
void InvertMask(struct IFFPic *pic);
void FreePicList(struct MinList *l);
void FreePicture(struct IFFPic *pic);

	/* from wire.c */

BOOL load_wire(struct WireFrame *wf,char *name);
BOOL draw_wire(struct WireFrame *wf,struct BitMap *bm);
BOOL free_wire(struct WireFrame *wf);

	/* forward declarations */

void close_all(int errnum);
checker_transition(struct BitMap *from, struct BitMap *to, int level);
struct UCopList *scan_cop(struct BitMap *a, struct BitMap *b, int scanline);
struct UCopList *slat_cop(struct BitMap *a, struct BitMap *b, int scanline);
roller_test(struct BitMap *a, struct BitMap *b);
install_cop(struct UCopList *cop);
void build_slab(struct IFFPic *pic, int border, int combsize);
blit_picture(struct IFFPic *source, struct BitMap *dest, int x, int y);
#pragma regcall( blit_picture(a0,a1,d0,d1) )
blitmask_picture(struct IFFPic *source, struct BitMap *dest, int x, int y, struct IFFPic *mask);
#pragma regcall( blitmask_picture(a0,a1,d0,d1,a2) )
blit_centered(struct IFFPic *source, struct BitMap *dest);
blit_centered_lace(struct IFFPic *source, struct BitMap *dest);
int handle_selection(struct RastPort *rp, struct Selector *blist, int count, int init);
ShowSelectBox(struct RastPort *, struct Selector *, int);
zoomrect(struct RastPort *rp, struct Selector *box, WORD *colorlist, int numcolors);
ozoomrect(struct RastPort *rp, struct Selector *box, WORD *colorlist, int numcolors);
/* fade_from_black(UWORD *palette, int steps); */
fade_to_black(UWORD *palette, int steps);
view_swap_pic(char *picname);
/* int validate_digits(char *s,int min,int max,int roll);
int validate_long(char *s,int min,int max,int roll); */
clear_bitmap(struct BitMap *b);
load_voice(char *voicename);
load_and_play_voice(char *voicename);
int play_sound_and_abrush(char *ab_name, char *samp_name, char *tname, int xpos, int ypos);

	/* needed when started up via WorkBench */
struct WBStartup		*WBMsg;

struct SimpleSprite		sprite0;
UWORD					*sprite_data;

UBYTE					shuffle160[160];

struct IFFPic			*stone1=NULL,
						*stone2=NULL,
						*stone3=NULL,
						*bevelm=NULL,
						*roller_track=NULL,
						*roller_sky=NULL;

struct MinList			perm_pics,
						temp_pics,
						transient_pics;				

	/* hard-wired copper lists for the roller coaster... */

struct MyCopList	*mc1, *mc2, *mc;
int					cop_switch = 0;

struct temp_slab {
	int					x,y,z;					/* position of slab				*/
	int					speed;					/* speed 0 means destroy?		*/
	int					comb_size;				/* which slab comb size to use. */
	struct IFFPic		*pic;
};

LONG seed1 = 1271921;

/* ==================================================================== */
/*						Color Animation Structures						*/
/* ==================================================================== */

UWORD					current_palette[32];	/* current active palette		*/
UWORD					intermediate_palette[32];
UWORD					backdrop_palette[32];
UWORD					picture_palette[32];
UWORD					black_palette[32];

	/* ======== The "TV Snow" color cycling effect... ======= */

UWORD					snow_colors[16];		/* low-saturation snow colors	*/
UWORD					hand_colors[32];		/* The wireframe hands palette	*/

	/* the first 16 colors are randomized, the next 16 are stable. All are used
		to produce the intermediate palette. After that, the intermediate palette
		is faded from (we can laso fade from white) to produce the final palette.
	*/

struct ColorEntry snow_animation[] = {
	{	NULL,				CycleColors,	1,15,	snow_colors+1, 	15,	1,0	}
};

struct ColorEntry snow_fader[] = {
	{	&snow_fader[1],		FadeTo,			1,15,	intermediate_palette+1, 0xEEE, 256,256 },
	{	NULL,				CopyColors, 	16,16,	hand_colors+16, 16,	10,0 }
};

struct ColorAnimation snow_fx[] = {
	{	&snow_fx[1],	snow_animation,		intermediate_palette,	NULL, NULL },
	{	NULL,			snow_fader,			current_palette,		NULL, NULL }
};

	/* ======== CDTV Logo Color Cycling ======== */

struct ColorEntry logo_cycle[] = {
	{	&logo_cycle[1],		CopyColors, 	0,8,	backdrop_palette,32,10,0 },
	{	NULL,				CycleColors,	8,24,	backdrop_palette+8, 24, 1,0	 }
};

struct ColorAnimation logo_fx[] = {
	{	NULL,				logo_cycle,		current_palette,		NULL, NULL }
};

	/* ======== "Green Pulse" Color Cycling ======== */

UWORD pulse_green[]  = { 0x080,0x090,0x0a0,0x0b0,0x0c0,0x0d0,0x0e0,0x0f0,0x0e0,0x0d0,0x0c0,0x0b0,0x0a0,0x090 };
UWORD pulse_red[]    = { 0x800,0x900,0xa00,0xb00,0xc00,0xd00,0xe00,0xf00,0xe00,0xd00,0xc00,0xb00,0xa00,0x900 };
UWORD pulse_yellow[] = { 0x880,0x990,0xaa0,0xbb0,0xcc0,0xdd0,0xee0,0xff0,0xee0,0xdd0,0xcc0,0xbb0,0xaa0,0x990 };
#define PULSE_COUNT		elementsof(pulse_green)

struct ColorEntry pulse_cycle[] = {
	{	&pulse_cycle[1],	CopyColors, 	0,32,	backdrop_palette,32,10,0 },
	{	NULL,				CycleColors,	16,1,	pulse_green,PULSE_COUNT, 1,0  }
};

struct ColorAnimation pulse_fx[] = {
	{	NULL,				pulse_cycle,	current_palette,		NULL, NULL }
};

	/* ======== "Data Flow" Color Cycling (includes Green Pulse) ======== */

struct ColorEntry data_cycle[] = {
	{	&data_cycle[1],	CopyColors, 	0,32,	backdrop_palette,32,10,0 },
	{	&data_cycle[2],	CycleColors,	16,1,	pulse_yellow,PULSE_COUNT, 1,0  },
	{	NULL,			ReverseCycle,	17,6,	backdrop_palette+17,6, 1,0  }
};

struct ColorAnimation data_fx[] = {
	{	NULL,			data_cycle,	current_palette,		NULL, NULL }
};

	/* ======== "IR Beams" Color Cycling (includes Green Pulse) ======== */

struct ColorEntry ir_cycle[] = {
	{	&ir_cycle[1],	CopyColors, 	0,32,	backdrop_palette,32,10,0 },
	{	&ir_cycle[2],	CycleColors,	16,1,	pulse_green,PULSE_COUNT, 1,0  },
	{	NULL,			CycleColors,	17,5,	backdrop_palette+17,5, 1,0  }
};

struct ColorAnimation ir_fx[] = {
	{	NULL,			ir_cycle,	current_palette,		NULL, NULL }
};

	/* ======== "Video Flow" Color Cycling (includes Green Pulse) ======== */

struct ColorEntry video_cycle[] = {
	{	&video_cycle[1],	CopyColors, 	0,32,	backdrop_palette,32,10,0 },
	{	&video_cycle[2],	CycleColors,	16,1,	pulse_green,PULSE_COUNT, 1,0  },
	{	NULL,				ReverseCycle,	25,6,	backdrop_palette+25,6, 1,0  }
};

struct ColorAnimation video_fx[] = {
	{	NULL,			video_cycle,	current_palette,		NULL, NULL }
};

	/* ======== "Video Flow II" Color Cycling (includes Green Pulse) ======== */

struct ColorEntry video2_cycle[] = {
	{	&video2_cycle[1],	CopyColors, 	0,32,	backdrop_palette,32,10,0 },
	{	&video2_cycle[2],	CycleColors,	16,1,	pulse_green,PULSE_COUNT, 1,0  },
	{	&video2_cycle[3],	ReverseCycle,	17,6,	backdrop_palette+17,6, 1,0  },
	{	NULL,				ReverseCycle,	25,6,	backdrop_palette+25,6, 2,0  }
};

struct ColorAnimation video2_fx[] = {
	{	NULL,			video2_cycle,	current_palette,		NULL, NULL }
};

	/* ======== "Video Flow III" Color Cycling (includes Green Pulse) ======== */

struct ColorEntry video3_cycle[] = {
	{	&video3_cycle[1],	CopyColors, 	0,32,	backdrop_palette,32,10,0 },
	{	&video3_cycle[2],	CycleColors,	16,1,	pulse_green,PULSE_COUNT, 1,0  },
	{	&video3_cycle[3],	ReverseCycle,	22,3,	backdrop_palette+22,3, 1,0  },
	{	&video3_cycle[4],	ReverseCycle,	25,3,	backdrop_palette+25,3, 1,0  },
	{	NULL,				ReverseCycle,	28,3,	backdrop_palette+28,3, 1,0  }
};

struct ColorAnimation video3_fx[] = {
	{	NULL,			video3_cycle,	current_palette,		NULL, NULL }
};

/* directions are up.down.left.right */
/* boxes are 	0	1
				2	3
				4
*/

struct Selector {
	struct IBox			box;
	UWORD				next[4];
};

struct Selector tutorial_selections[] = {
	{	 34,  3, 107,73,		4,2,4,1 },
	{	180,  3, 107,73,		3,3,0,2 },
	{	 34, 75, 107,74,		0,4,1,3 },
	{	180, 75, 107,74,		1,1,2,4 },
	{	 24,147,  55,44,		2,0,3,0 }
/*	{	248,147,  55,52,		?,?,?,? } */
};

struct Selector main_selections[] = {
	{	 34,  3, 107,73,		2,2,3,1 },
	{	180,  3, 107,73,		3,3,0,2 },
	{	 34, 75, 107,74,		0,0,1,3 },
	{	251,154,  55,43,		1,1,2,0 }
};

struct Selector credit_selections[] = {
	{	 19,147,  54,44,		1,1,1,1 },
	{	219,126,  99,74,		0,0,0,0 }
};

struct Selector slab_selections[] = {
	{	 25, 43, 118,78 },
	{	209, 43, 118,78 },
	{	 25,153, 118,78 },
	{	209,153, 118,78 }
};

WORD tutorial_zoom[] = { 0,11,12,13,3 };
WORD main_zoom[] = { 0,25,26,27,3 };
WORD slab_zoom[] = { 0,1,2,3,4,5,6,7 };

int						tutorial_selection = 0,
						tutorial_explain = TRUE,
						main_selection=1,
						credit_selection,
						main_explain = TRUE;

struct IFFPic			*swap_pic=NULL, *last_swap_pic = NULL;

#define PIC_SIZES		40

#define COMB_SIZES		16
UWORD					comb_offset[COMB_SIZES];
UBYTE					comb_heights[COMB_SIZES] = {
	56, 46, 39, 34, 30, 27, 24, 22, 21, 19, 17, 16, 13, 11, 9, 8
};
struct IFFPic			*comb_pics[COMB_SIZES];

struct month_data {
	char				*monthname;
	UBYTE				days;
} month_table[12] = {
	"Jan ",	31,
	"Febr ",	28,
	"March ",	31,
	"April ",	30,
	"May ",	31,
	"June ",	30,
	"July ",	31,
	"Aug ",	31,
	"Sept ",	30,
	"Oct ",	31,
	"Nov ",	30,
	"Dec ",	31
};

struct WireFrame		wire_data;
struct AnimHandle		anim_data;
struct CompAnimHandle	comp_anim_data;
struct DiskAnimHandle	disk_anim_data;

WORD slab_start_x[] = {
	((OSCAN_WIDTH - 112)/2 - 16 + 0*8),
	((OSCAN_WIDTH - 112)/2 - 16 + 1*8),
	((OSCAN_WIDTH - 112)/2 - 16 + 2*8),
	((OSCAN_WIDTH - 112)/2 - 16 + 3*8)
};

WORD slab_start_y[] = {
	((OSCAN_HEIGHT - 72)/2 - 8 + 0*8),
	((OSCAN_HEIGHT - 72)/2 - 8 + 1*8),
	((OSCAN_HEIGHT - 72)/2 - 8 + 2*8),
	((OSCAN_HEIGHT - 72)/2 - 8 + 3*8)
};

WORD slab_stop_x[] = { 28, 212, 28, 212 };
WORD slab_stop_y[] = { 46, 46, 156, 156 };

_main(long alen,char *aptr)
{	extern char			quit_key,
						music_key, nextsong_key;
	int					i,j;
	char				key;
	long				length;
	short				x,y;
	char				*text;
	int					argc;
	LOCK				lock;
	struct				BitMap bm;
	void SyncMusic(struct Task *task,UBYTE sigbit);
	int					section = 0;
	struct UCopList		*temp_cop=NULL;
	struct RastPort		temp_rp;
	char				cname[16] = "data/Comb.s##";
	struct temp_slab	four_slabs[4];

		/* iff pictures used... */

	struct IFFPic		*tv_snow,
						*ocean=NULL,
						*hands=NULL,
						*hmask=NULL,
						*cdtv1=NULL,
						*menu_pic,
						*gramaphone;

	myprocess = (struct Process *)FindTask(NULL);

	if (myprocess->pr_CLI)
	{
		argc = (alen ? 2 : 1);
	}
	else
	{	argc = 0;
		WaitPort(&myprocess->pr_MsgPort);
		WBMsg = (struct WBStartup *)GetMsg(&myprocess->pr_MsgPort);
	/*	olddir = CurrentDir((LOCK)WBMsg->sm_ArgList->wa_Lock); */
	}

	AddIntServer(INTB_VERTB, &VertBlank);			/* add interrupt server */

	if (argc > 1)
	{	text = aptr;
		i = alen;
		while (i && *text == ' ') { text++; i--; }
		while (i--)
		{	
			if (isdigit(*text))
			{	section = *text++ - '0';

				while (isdigit(*text)) section = section * 10;
			}
			text++;
		}
	}

	NewList((struct List *)&perm_pics);
	NewList((struct List *)&temp_pics);
	NewList((struct List *)&transient_pics);

	error = 0;

	unless (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0))
		close_all(DERR_NO_LIBRARY);
	oldview = GfxBase->ActiView;

	unless (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0))
		close_all(DERR_NO_LIBRARY);

/*	xoffset = clamp(0,oldview->DxOffset - (OSCAN_WIDTH - STD_WIDTH) / 2,256);
	yoffset = clamp(0,oldview->DyOffset - (OSCAN_HEIGHT - STD_HEIGHT) / 2,256);
*/

		/* Hard code the view position. Normally would be set with preferences. */
		/* Note that we use NTSC height for both NTSC and PAL, because in PAL
			only lower part is changed...
		*/

		/* REM: Need to adjust this using preferences... */

	xoffset = 0x81 - (OSCAN_WIDTH - STD_WIDTH) / 2 /* - 16 */ ;
/*	yoffset = 0x2c - (NTSC_HEIGHT - STD_HEIGHT) / 2; */
	yoffset = 0x24 - (NTSC_HEIGHT - STD_HEIGHT) / 2;
	if (GfxBase->DisplayFlags & PAL) yadjust = 0;
	else yadjust = (OSCAN_HEIGHT - NTSC_HEIGHT) / 2;

		/* figure out how to center game on user's screen */

#if 0
	if (GetScreenData((char *)&screen,sizeof screen,WBENCHSCREEN,NULL))
	{
		/*	We will only shift things around if the display appears
			"normal"; i.e. there is no "vscreen", etc., lurking around. */	

		if (screen.ViewPort.DWidth >= screen.Width &&
			screen.ViewPort.DHeight >= screen.Height)
		{
			if (screen.ViewPort.Modes & HIRES)
				xoffset += (screen.Width - 640) / 4;
			else xoffset += (screen.Width - 320) / 2;

			if (screen.ViewPort.Modes & LACE)
				yoffset += (screen.Height - 400) / 4;
			else yoffset += (screen.Height - 200) / 2;
		}
	}
#endif

	if (xoffset < MIN_VIEW_DX) xoffset = MIN_VIEW_DX;

	unless (InitKeyConvert()) close_all(DERR_NO_DEVICE);
	unless (init_gameport()) close_all(DERR_NO_DEVICE);
	unless (add_device()) close_all(DERR_NO_DEVICE);
	unless (add_interrupt()) close_all(DERR_NO_INTERRUPT);

	if (PLAY_MUSIC && InitMusic() == 0) close_all(DERR_MUSIC_ON);
	SuspendMusic();

	patch_autorequest();				/* Do we really need this??? */

	unless (init_ucop()) close_all(DERR_NO_MEMORY);

	if (add_null()) close_all(DERR_NO_MEMORY);
	loadview(&v_null);

	FreeSprite(0);

	unless (sprite_data = AllocMem(12L,MEMF_CHIP|MEMF_CLEAR)) close_all(DERR_NO_MEMORY);

	if (GetSprite(&sprite0,0) != 0) close_all(DERR_NO_SPRITE);

	ChangeSprite(&vp_null,&sprite0,(void *)sprite_data);

#if DEBUG
		/* to run from CLI, MUST be current dir */
/*	if (argc > 0)
	{	LOCK			lock;

		unless (lock = Lock("Discovery:",ACCESS_READ)) close_all(DERR_CANT_LOCK);
		olddir = CurrentDir(lock);
	} */
#endif

	TopazFont = OpenFont(&topaz_8);

		/* prevent DOS Library from putting up requesters */
	oldWindowPtr = myprocess->pr_WindowPtr;
	myprocess->pr_WindowPtr = (APTR)-1;

	unless (bink_sample = load_sample(BINKSOUND)) close_all(DERR_NO_MEMORY);
	unless (bell_sample = load_sample(BELLSOUND)) close_all(DERR_NO_MEMORY);

	if (!closedwb)
	{	CloseWorkBench();
		FreeSprite(0);
		closedwb = 1;
	}

	InitRastPort(&rp_text);
/*	SetFont(&rp_text,&CarnelianFont); */

	if (section) tutorial_explain = main_explain = 0;

newdemo:
	if (!MakeBitMap(&bm_main,EHB_DEPTH,OSCAN_WIDTH,2*OSCAN_HEIGHT))
		close_all(DERR_NO_MEMORY);

	add_title();
	vport = &vp_main;

	reset_skip();					/* check current button state */

	if (PLAY_MUSIC && LoadPlayXSong(INTROTHEME, 0) == 0)
	{	remove_title();
		close_all(DERR_NO_MEMORY);
	}

	remake_title();
	fp_drawing = &fp_page2; fp_viewing = &fp_page1;

	if (section > ROLLER_SECTION) goto intro_end;
	load_picture_and_voice("data/legals01.pic",NULL);
	if (delayed_skip(100)) goto intro_end;

	if (section > GLOBE_SECTION) goto globe_section_end;
	if (SKIPPED) goto intro_end;

	if (LoadDiskAnim(&disk_anim_data,"data/comspin.anim"))
	{	int	count = 0,rev;

		while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap) &&
			!SKIPPED)
		{	
			/* also, do various beeps at certain frame intervals... */
			/* also, play the asynchronous sound sample for "welcome to CDTV" [?] */
			/* also, check for button presses and do highlight... */
				
			wait_cop();
			new_pageflip(disk_anim_data.colors);

			if (count == 0)
			{	load_and_play_voice("data/samp.1001");
			}

			if (count >= 10*17+4) break;

			rev = (count-9)/17;
			if (rev < 9 && rev*17 == count-9)
			{	play_sample(bink_sample);
			}
			else if (rev < 10) { WaitTOF(); WaitTOF(); }
			count++;
		}
		FreeDiskAnim(&disk_anim_data);
	}
	if (skipped) goto intro_end;

	LoadRGB4(vport,black_palette,LORES_COLORS);

globe_section_end:

	/* Add in CD_RAINBOW section.... */

#if 0
		/* build a random table, used by the transition... */
		/* only used by checker transition */
	for (i=0; i<160; i++) shuffle160[i] = i;
	for (i=0; i<1000; i++)
	{	short q, j;
		q = rand() % 160;
		j = shuffle160[q];	shuffle160[q] = shuffle160[0]; shuffle160[0] = j;
	}
#endif

	seed1 = 1271921;						/* reset the seed... */
	rand();

	/* ==================================================================== */
	/*								Ocean Scene 1							*/
	/* ==================================================================== */

	if (section >= NATIONPICS_SECTION) goto ocean_section_end;

	clear_main();

	fp_drawing = &fp_page2; fp_viewing = &fp_page1;

	/* ==================================================================== */
	/*								CD Tunnel Scene							*/
	/* ==================================================================== */

	if (unpackpic("data/Tunnel.Oscan",fp_drawing->ri_page->BitMap,backdrop_palette))
	{	UWORD	palette_queue[32];

		for (j=0; j<32; j++) palette_queue[j] = 0;

		for (i=0; i<512; i++)
		{	WORD	r,g,b;
			LONG	k,q;
				/* We'll limit it to blue pulses for now... */

			for (j=31; j>1; j--)
			{	palette_queue[j] = palette_queue[j-1];
			}

			r = (i /  5) & 31; if (r > 15) r = 31 - r;
			g = (i /  3) & 31; if (g > 15) g = 31 - g;
			b = (i /  2) & 31; if (b > 15) b = 31 - b;

			q = clamp(0,i/2-220,14);

			r = clamp(q,r,14);
			g = clamp(q,g,14);
			b = clamp(q,b,14);

			palette_queue[1] = (r<<8) + (g<<4) + b;

			CopyMem(palette_queue,picture_palette,sizeof picture_palette);

			k = (q * 0x1000) + 0x2000;
			q = 0;

			for (j=1; j<9; j++)
			{	InterpolateColors(
					&black_palette[0],
					&palette_queue[j],
					&picture_palette[j],
					1,
					MAX(q,k));
				q += 0x2000;
			}

			if (i == 0) new_pageflip(picture_palette);
			else LoadRGB4(&vp_main,picture_palette,LORES_COLORS);
			wait_cop();

			if (skipped) goto intro_end;
		}
	}

	/* ==================================================================== */
	/*								TV Snow									*/
	/* ==================================================================== */

	tv_snow = GetPicture(SNOW1,snow_colors,16,&transient_pics);
	hands = GetPicture(HANDS1,hand_colors,LORES_COLORS,&transient_pics);
	unless (tv_snow && hands) goto ocean_section_end;

		/* load pictures needed for next scene. */

	unless (hmask = MakeMask(hands,&transient_pics)) goto ocean_section_end;

	channel_sample = load_sample("data/TVChannel.Sample");
	async_sample   = load_sample("data/TVSnow.Sample"); 

/*	BltBitMap(&tv_snow->bmap,0,0,fp_drawing->ri_page->BitMap,0,0,
		tv_snow->width,tv_snow->height, 0xC0, 0xFF, NULL);
*/
	OwnBlitter();
	blit_picture(tv_snow,fp_drawing->ri_page->BitMap,0,0);
	blitmask_picture(hands,fp_drawing->ri_page->BitMap,30,OSCAN_HEIGHT/2,hmask);
	DisownBlitter();

	wait_cop();
	new_pageflip(NULL);
	snow_fx[1].result_viewport = vport;
	current_palette[0] = 0;
	color_list = snow_fx;

	if (async_sample) play_continuous(async_sample);

	for (i=0; i<=256; i+=8)
	{	snow_fader[0].fade_level = i;
		if (delayed_skip(2)) goto intro_end;
	}

	ocean = GetPicture(OCEAN1,backdrop_palette,LORES_COLORS,&temp_pics);
	unless (ocean) goto ocean_section_end;

	CopyMem(backdrop_palette,hand_colors,16*sizeof (UWORD));

#if 0
	if (SKIPPED) goto intro_end;

snow_section_end:

	/* ==================================================================== */
	/*						Wire frame hands over TV Snow					*/
	/* ==================================================================== */

	for (i=0; i<=(OSCAN_HEIGHT/2); i+=4)
	{	struct BitMap *b = fp_drawing->ri_page->BitMap;

		LoadRGB4(vport,current_palette,16);		/* load palette manually		*/

		OwnBlitter();
		blit_picture(tv_snow,b,0,0);
		blitmask_picture(hands,b,30,OSCAN_HEIGHT-i,hmask);
		DisownBlitter();

		if (SKIPPED) goto intro_end;

		wait_cop();
		new_pageflip(NULL);
	}

		/* ANIMATE moving hands and SYNC to audio here... */
#endif

/*	if (delayed_skip(40)) goto intro_end; */

		/* put in ocean on second bitmap... */

	OwnBlitter();
	blit_picture(ocean,fp_drawing->ri_page->BitMap,0,0);
	blitmask_picture(hands,fp_drawing->ri_page->BitMap,30,(OSCAN_HEIGHT/2),hmask);
	DisownBlitter();

	/* ==================================================================== */
	/*						Change Channels to Ocean						*/
	/* ==================================================================== */

	if (async_sample)
	{	stop_async(async_sample);
		unload_sample(async_sample);
		async_sample = NULL;
	}

		/* a flash of white as we change channels... */

	snow_fader[0].fade_level = 0;				/* single frame of white		*/
	wait_cop();									/* wait for frame end			*/
	wait_cop();									/* wait for frame end			*/
	color_list = NULL;							/* stop color animating			*/

	if (channel_sample)
	{	play_sample(channel_sample);
		unload_sample(channel_sample);
		channel_sample = NULL;
	}

	Delay(2);									/* wait just a little bit		*/
	new_pageflip(hand_colors);					/* flip to ocean page			*/

	/* ==================================================================== */
	/*						Wire frame hands over ocean						*/
	/* ==================================================================== */

		/* ANIMATE moving hands and SYNC to audio here... */

	SyncMusic((struct Task *)myprocess,SIGBREAKB_CTRL_E);
	SetSignal(0L,SIGBREAKF_CTRL_E);				/* wait for the music...			*/
	PlaySong(0);								/* start the music				*/

	if (SKIPPED) goto intro_end;

	for (i=0; i<COMB_SIZES; i++)
	{	struct IFFPic *pic;

		cname[11] = i/10 + '0';
		cname[12] = i % 10 + '0';

		comb_pics[i] = GetPicture(cname,NULL,0,&temp_pics);
		comb_offset[i] = 0;
	}

/*	if (delayed_skip(50)) goto intro_end; */

	for (i=0; i<=(OSCAN_HEIGHT/2); i+=4)
	{	struct BitMap *b = fp_drawing->ri_page->BitMap;

		OwnBlitter();
		blit_picture(ocean,b,0,0);
		blitmask_picture(hands,b,30,(OSCAN_HEIGHT/2)+i,hmask);
		DisownBlitter();

		if (SKIPPED) goto intro_end;

		wait_cop();
		new_pageflip(NULL);
	}

	/* ==================================================================== */
	/*						Animated Slabs over ocean #1					*/
	/* ==================================================================== */

	FreePicList(&transient_pics);				/* free hand pictures...		*/
	LoadRGB4(vport,backdrop_palette,LORES_COLORS);	/* use pure ocean colors...		*/

		/* Load the set of pictures needed for the flying stones... */

	bevelm = GetPicture(BEVEL,NULL,0,&temp_pics);
	stone1 = GetPicture(STONE1,NULL,0,&temp_pics);
	stone2 = GetPicture(STONE2,NULL,0,&temp_pics);
	stone3 = GetPicture(STONE3,NULL,0,&temp_pics);

	if (bevelm && stone1 && stone2 && stone3)
	{	struct temp_slab	list[40];

			/* fade up while we are building... */

		InitRastPort(&rp_slab);

		for (i=0; i<elementsof(list); i++)
		{	struct temp_slab *t = &list[i];
			struct IFFPic *slab_pic;
			int			w,h, cw;

			w = 500 / ((i+i)/3+5);		/* WAS i/2 --DJ */
			h = 340 / ((i+i)/3+5);

			t->pic = MakePicture(w,h,5,&transient_pics);

		/*	Printf("%ld Slab Sizes: %ld %ld\n",i, w - w/10, h - w/10); */

			/* pull the slab picture off the Ith slab list,
					blit it onto the slab, and then put it on the
					transient list to be de-alloc'd
			*/

			cw = w - w/10;			/* comb width... */

			for (j=0; j<COMB_SIZES; j++)
			{	t->comb_size = j;
				if (comb_pics[j]->width <= cw && comb_heights[j] < h) break;
			}

			build_slab(t->pic,w/20,t->comb_size);

			t->x = 2 * (- (rand() % 600) - w - 20);
			t->y = (rand() % 100) - (rand() % 100) - (h / 2) + OSCAN_HEIGHT/2;
			t->speed = w/5;
		}


		for (i=0; i<4; i++)
		{	struct temp_slab *t = &four_slabs[i];
			char		slabname[] = "data/slab.01";

			slabname[11] = i + '1';

			t->pic = GetPicture(slabname,NULL,0,&transient_pics);
			t->y = ((OSCAN_HEIGHT - 72)/2 - 8 + i*8);
			t->speed = 112/15;
			t->x = - 200 - i*100;
		}

			/* animate the slabs moving... */

		Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/

		for (i=0; i<3500; i+=4)
		{	struct BitMap *b = fp_drawing->ri_page->BitMap;

				/* redraw background */

			/* own blitter... */

			OwnBlitter();

			blit_picture(ocean,b,0,0);

			for (j=elementsof(list)-1; j >=0; j--)
			{	struct temp_slab *t = &list[j];
				if (t->x/3 + t->pic->width >= 0)
					blit_picture(t->pic,b,t->x/3,t->y);
				t->x += t->speed;
			}

				/* blit in the special ones... (the magic hat, etc.) */

			for (j=0; j <4; j++)
			{	struct temp_slab *t = &four_slabs[j];
				int		limit = (OSCAN_WIDTH - 112)/2 - 16 + j*8;

			/*	at time i, which is 600, 800 1000 1200 */
			/* let's adjust this... */

				t->x = 2 * clamp(-150,i-450-j*160,0) + limit;

				if (t->x + t->pic->width >= 0)
					blit_picture(t->pic,b,t->x,t->y);
			}

			/* disown blitter */
			DisownBlitter();

			for (j=elementsof(list)-1; j >=0; j--)
			{	struct temp_slab *t = &list[j];
				if (t->x > OSCAN_WIDTH*3)
				{	struct IFFPic *slab_pic;
					
					/* pull the slab picture off the Ith slab list,
						blit it onto the slab, and then put it on the
						transient list to be de-alloc'd

					*/
					build_slab(t->pic,t->pic->width/20,t->comb_size);

					t->x = (- (rand() % 300) - t->pic->width - 20) * 2;
					t->y = (rand() % 100) - (rand() % 100) - (t->pic->height / 2) + OSCAN_HEIGHT/2;
					/* t->speed = w/10; */
				}
			}

			if (SKIPPED) goto intro_end;

				/* flip page... */

			wait_cop();
			new_pageflip(NULL);

			if (SetSignal(0L,SIGBREAKF_CTRL_E) & SIGBREAKF_CTRL_E) break;
		}


			/* save picture... */

	/*	SavePic("ram:temp.pic",fp_viewing->ri_page->BitMap, backdrop_palette, 32); */


		/* now, the random placement of slabs... */

		for (i=0; i<3000; i++)
		{	struct BitMap *b = fp_viewing->ri_page->BitMap;
			struct temp_slab *t;
			struct IFFPic *slab_pic;

				/* pick a random slab out of the first 20 */

			j = rand() % 20;
			t = &list[j];

				/* blit it to a random spot on the screen */

			OwnBlitter();

			blit_picture(t->pic,b,
				rand() % OSCAN_WIDTH - t->pic->width/2,
				rand() % OSCAN_HEIGHT - t->pic->height/2 );

			DisownBlitter();

				/* now, regenerate it with a new picture */

			build_slab(t->pic,t->pic->width/20,t->comb_size);

			if (SKIPPED) goto intro_end;

			if (playflag == 0) break;
		}
	}

#if 0
	/* ==================================================================== */
	/*						Some Test Transitions...						*/
	/* ==================================================================== */

cdtv1_section:
	goto ocean_section_end;					/* skip over CDTV transitions... */

	FreePicList(&transient_pics);
	if (cdtv1 = GetPicture(CDTV1,picture_palette,elementsof(picture_palette),&transient_pics))
	{	struct BitMap *b = fp_drawing->ri_page->BitMap;

		if (SKIPPED) goto intro_end;

		BltBitMap(&cdtv1->bmap,0,0,
			b,0,0,
			cdtv1->width,cdtv1->height,
			0xC0, 0xFF, NULL);

		mtv_fx[1].result_viewport = vport;
		color_list = mtv_fx;

		if (SKIPPED) goto intro_end;

			/* do the transition... with copper lists? */

			/* go from ocean to MTV */

		init_transitions();
		for (i=0; i<TRANSITION_MAX; i += TRANSITION_STEPS(160))
		{	checker_transition( &cdtv1->bmap, fp_viewing->ri_page->BitMap, i);
			wait_cop();
			if (SKIPPED) goto intro_end;
		}

			/* back to ocean */

		init_transitions();
		for (i=0; i<TRANSITION_MAX; i += TRANSITION_STEPS(160))
		{	raster_transition( &ocean->bmap, fp_viewing->ri_page->BitMap, i);
			wait_cop();
			if (SKIPPED) goto intro_end;
		}

			/* copper list back to MTV */

		for (i=1; i<OSCAN_HEIGHT/8; i++)
		{	wait_cop();
			/* need to modify the base palette of vport... */
			if (temp_cop = slat_cop(fp_viewing->ri_page->BitMap,b,i))
				install_cop(temp_cop);
			if (delayed_skip(2)) goto intro_end;
		}

			/* copy the second page to the first... */

		BltBitMap(&cdtv1->bmap,0,0,
			fp_viewing->ri_page->BitMap,0,0,
			cdtv1->width,cdtv1->height,
			0xC0, 0xFF, NULL);

			/* now, show the whole "viewing" page */

		install_cop(NULL);				/* reset to default copper list	*/
		wait_cop();
		free_cops();							/* now, free those copper lists */

		if (delayed_skip(50)) goto intro_end;

			/* fade out... */

		for (i=256; i>=0; i--)
		{	mtv_fader[0].fade_level = i;
			if (delayed_skip(1)) goto intro_end;
		}

		color_list = NULL;
	}
#endif

ocean_section_end:

	color_list = NULL;
	FreePicList(&transient_pics);
	FreePicList(&temp_pics);

	fp_drawing = &fp_page2;						/* re-sync flipped pages...		*/
	fp_viewing = &fp_page1;
	fp_page1.ri_page = &ri_page1;
	fp_page2.ri_page = &ri_page2;

	/* ==================================================================== */
	/*							Nation Flip Pics							*/
	/* ==================================================================== */

	SuspendMusic();

	last_swap_pic = swap_pic = NULL;

	if (section <= NATIONPICS_SECTION)
	{
		vp_main.RasInfo = &ri_pic;
		vp_main.UCopIns = ucl;
		ri_pic.RxOffset = ri_pic.RyOffset = 0;
		ri_pic.Next = NULL;

		view_swap_pic(CDFIN);
		logo_fx[0].result_viewport = vport;		/* set up color animation		*/
		color_list = logo_fx;					/* color animate this picture	*/

		load_and_play_voice("data/samp.1002");
		if (delayed_skip(50)) goto intro_end;

			/* french */

		if (load_voice("data/samp.1003")) play_async(voice_sample);

#if 0
		if (OpenCat("data/slideshow.cat"))
		{	for (i=0; i<10; i++) view_swap_pic(NULL);
			CloseCat();
		}
#else
		view_swap_pic("data/SlideShow.01");
		view_swap_pic("data/SlideShow.02");
		view_swap_pic("data/SlideShow.03");
		view_swap_pic("data/SlideShow.04");
		view_swap_pic("data/SlideShow.05");
		view_swap_pic("data/SlideShow.06");
		view_swap_pic("data/SlideShow.07");
		view_swap_pic("data/SlideShow.08");
		view_swap_pic("data/SlideShow.09");
		view_swap_pic("data/SlideShow.10");
#endif

		if (voice_sample)
		{	wait_async(voice_sample);
			unload_sample(voice_sample);
			voice_sample = NULL;
		}

		view_swap_pic(CDFIN);
		logo_fx[0].result_viewport = vport;		/* set up color animation		*/
		color_list = logo_fx;					/* color animate this picture	*/

/*		load_and_play_voice("data/SAMPLE057"); */
		if (delayed_skip(100)) goto intro_end;

		title_to_lores();
	}

		/*	Now, Show the four ocean squares... */


		/* Show four slabs and then zoom to Information */

	InitRastPort(&rp_slab);
	color_list = NULL;							/* color animate this picture	*/

	if (ocean = GetPicture("data/Ocean.oscan",backdrop_palette,LORES_COLORS,&temp_pics))
	{	int				smoothval;

		for (i=0; i<4; i++)
		{	struct temp_slab *t = &four_slabs[i];
			char		slabname[] = "data/slab.01";

			slabname[11] = i + '1';

			t->pic = GetPicture(slabname,NULL,0,&transient_pics);
		}

		LoadRGB4(&vp_main,backdrop_palette,LORES_COLORS);

		for (smoothval = 0; smoothval <= 256; smoothval+=8)
		{	struct BitMap *b = fp_drawing->ri_page->BitMap;
			OwnBlitter();
			blit_picture(ocean,b,0,0);

			for (j=0; j<4; j++)
			{	int		x,y;

				x = (slab_start_x[j] * (256-smoothval) + slab_stop_x[j] * smoothval) / 256;
				y = (slab_start_y[j] * (256-smoothval) + slab_stop_y[j] * smoothval) / 256;

				blit_picture(four_slabs[j].pic,b,x,y);
			}

			DisownBlitter();

			if (SKIPPED) goto intro_end;
			wait_cop();
			new_pageflip(NULL);
			if (smoothval == 0)
			{	if (load_voice("data/samp.1004")) play_async(voice_sample);
			}
		}
	}

	if (voice_sample)
	{	wait_async(voice_sample);
		unload_sample(voice_sample);
		voice_sample = NULL;
	}

	play_sound_and_abrush("data/info.abr","data/samp.1005","data/infot.anim",56,57);

#if 0
	/* !!! */

	/* need to fill in position to play anim at.
		Another arg is sample name and abr name.

		Problem: There are two samples to do!!!
		(We'll have to combine them...)
		1005-1006
		1007-1008-1009
		1010-1011
		1012-1013
	*/

{	struct BitMap *animb;

	LoadAnim(&anim_data,"data/info.abr");
	animb = ResetAnim(&anim_data,2);			/* continuous... */

		/* repeat until sound finished... */

	if (load_voice("data/samp.1005")) play_async(voice_sample);
	BltBitMap(fp_viewing->ri_page->BitMap,0,0,fp_drawing->ri_page->BitMap,0,0,
		OSCAN_WIDTH,OSCAN_HEIGHT, 0xC0, 0xFF, NULL);

	while (!SKIPPED)
	{	if (voice_sample && check_async(voice_sample)) break;

		BltBitMap(animb,0,0,fp_drawing->ri_page->BitMap,40,40,
			anim_data.width,anim_data.current->bm.Rows, 0xC0, 0xFF, NULL);
		wait_cop();
		new_pageflip(NULL);
		animb = NextAnimFrame(&anim_data);
	}
	FreeAnim(&anim_data);

	if (voice_sample)
	{	wait_async(voice_sample);
		unload_sample(voice_sample);
		voice_sample = NULL;
	}

	if (skipped) goto intro_end;
}
/* #else */

	load_anim_and_voice("data/infot.Anim","data/samp.1005");
	play_voice();		/* need to play this asynchronously... */

	load_anim_and_voice("data/infot.Anim",NULL);
	for (;;)
	{	Delay(3);
		NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
		new_pageflip(NULL);
		if (comp_anim_data.current == NULL) break;
	}
	FreeCompAnim(&comp_anim_data);
#endif
	if (SKIPPED) goto intro_end;

	SyncMusic((struct Task *)myprocess,SIGBREAKB_CTRL_E);
	SetSignal(0L,SIGBREAKF_CTRL_E);
	PlaySong(1);								/* start the music				*/

	load_picture_and_voice("data/FakeInfoScreen.Pic",NULL);		/* art history	*/
	if (delayed_skip(200)) goto intro_end;

	load_picture_and_voice("data/FakeInfoScreen4.Pic",NULL);	/* neptune		*/
	if (delayed_skip(180)) goto intro_end;

	load_picture_and_voice("data/FakeInfoScreen2.Pic",NULL);	/* england		*/
	if (delayed_skip(180)) goto intro_end;

	load_picture_and_voice("data/FakeInfoScreen6.Pic",NULL);	/* metals		*/
	if (delayed_skip(120)) goto intro_end;

	load_picture_and_voice("data/FakeInfoScreen5.Pic",NULL);	/* jupiter		*/
	if (delayed_skip(180)) goto intro_end;

	load_picture_and_voice("data/FakeInfoScreen3.Pic",NULL);	/* saturn		*/
	if (delayed_skip(200)) goto intro_end;

		/* REM: Need more pictures... */

	SuspendMusic();

		/* Show four slabs and then zoom to Education */

	play_sound_and_abrush("data/edu.abr","data/samp.1007","data/educationt.anim",247,56);

#if 0
	load_picture_and_voice("data/FourSlabs.Pic",NULL);

	rp_slab.BitMap = fp_viewing->ri_page->BitMap;
	ozoomrect(&rp_slab,&slab_selections[1],slab_zoom,7);
/* #else */
	load_anim_and_voice("data/educationt.Anim","data/samp.1007"); play_voice();

	for (;;)
	{	Delay(3);
		NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
		new_pageflip(NULL);
		if (comp_anim_data.current == NULL) break;
	}
	FreeCompAnim(&comp_anim_data);
#endif
	if (SKIPPED) goto intro_end;

	SyncMusic((struct Task *)myprocess,SIGBREAKB_CTRL_E);
	SetSignal(0L,SIGBREAKF_CTRL_E);
	PlaySong(2);								/* start the music				*/

	load_picture_and_voice("data/FakeEduScreen5.Pic",NULL);		/* pets			*/
	if (delayed_skip(100)) goto intro_end;

	load_picture_and_voice("data/FakeEduScreen6.Pic",NULL);		/* pythagoras	*/
	if (delayed_skip(100)) goto intro_end;

	load_picture_and_voice("data/FakeEduScreen3.Pic",NULL);		/* rocket		*/
	if (delayed_skip(100)) goto intro_end;

	load_picture_and_voice("data/FakeEduScreen4.Pic",NULL);		/* molecule		*/
	if (delayed_skip(130)) goto intro_end;

	load_picture_and_voice("data/FakeEduScreen.Pic",NULL);		/* math			*/
	if (delayed_skip(100)) goto intro_end;

	if (playflag)
	{	load_picture_and_voice("data/FakeEduScreen2.Pic",NULL);	/* wind tunnel	*/
		if (delayed_skip(100)) goto intro_end;
	}

	while (playflag) Delay(5);					/* wait for song to finish...	*/

		/* REM: Need more pictures... */

	SuspendMusic();

		/* Show four slabs and then zoom to Entertainment */

	play_sound_and_abrush("data/ent.abr","data/samp.1010","data/entertainmentt.anim",33,160);
#if 0
	load_anim_and_voice("data/entertainmentt.Anim","data/samp.1010"); play_voice();

	for (;;)
	{	Delay(3);
		NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
		new_pageflip(NULL);
		if (comp_anim_data.current == NULL) break;
	}
	FreeCompAnim(&comp_anim_data);
#endif
	if (SKIPPED) goto intro_end;

	if (LoadDiskAnim(&disk_anim_data,"data/hyper.anim"))
	{	PlaySong(3);								/* start the music			*/
		while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap) &&
			!SKIPPED)
		{	wait_cop();
			new_pageflip(disk_anim_data.colors);
			WaitTOF(); WaitTOF();
		}
		FreeDiskAnim(&disk_anim_data);
	}
	if (LoadDiskAnim(&disk_anim_data,"data/orbital.anim"))
	{	while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap) &&
			!SKIPPED)
		{	wait_cop();
			new_pageflip(disk_anim_data.colors);
			WaitTOF(); WaitTOF();
		}
		FreeDiskAnim(&disk_anim_data);
	}
	if (SKIPPED) goto intro_end;
	while (playflag) Delay(5);					/* wait for song to finish...	*/
	SuspendMusic();

		/* Show four slabs and then zoom to Music */

	play_sound_and_abrush("data/mus.abr","data/samp.1012","data/musict.anim",241,164);
#if 0
	load_anim_and_voice("data/musict.Anim","data/samp.1012"); play_voice();

	for (;;)
	{	Delay(3);
		NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
		new_pageflip(NULL);
		if (comp_anim_data.current == NULL) break;
	}
	FreeCompAnim(&comp_anim_data);
#endif
	if (SKIPPED) goto intro_end;

	if (LoadDiskAnim(&disk_anim_data,"data/BradStuff/Music2.PAL.anim"))
	{	int jif = 40;

		SyncMusic((struct Task *)myprocess,SIGBREAKB_CTRL_E);
		SetSignal(0L,SIGBREAKF_CTRL_E);			/* wait for the music...		*/
		PlaySong(4);							/* start the music				*/

		while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap) &&
			!SKIPPED)
		{	wait_cop();
			new_pageflip(disk_anim_data.colors);
			for (i=0;i<jif;i++) WaitTOF();
			jif = 2;
		}
		FreeDiskAnim(&disk_anim_data);
	}
	if (skipped) goto intro_end;

		/* animate to the guitar */

	if (LoadDiskAnim(&disk_anim_data,"data/BradStuff/Music3.PAL.anim"))
	{	Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/
		while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap) && !SKIPPED)
		{	wait_cop();
			new_pageflip(NULL);
			WaitTOF(); WaitTOF();
		}
		FreeDiskAnim(&disk_anim_data);
	}
	if (SKIPPED) goto intro_end;

		/* animate to the keyboard */

	if (LoadDiskAnim(&disk_anim_data,"data/BradStuff/Music4.PAL.anim"))
	{	Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/
		while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap) && !SKIPPED)
		{	wait_cop();
			new_pageflip(NULL);
			/* WaitTOF(); */ WaitTOF();
		}
		FreeDiskAnim(&disk_anim_data);
	}

	if (SKIPPED) goto intro_end;
	Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/
	load_picture_and_voice("data/BradStuff/Music5.PAL.pic",NULL);
	if (SKIPPED) goto intro_end;
	Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/
	load_picture_and_voice("data/BradStuff/Music6.PAL.pic",NULL);
	if (SKIPPED) goto intro_end;
	Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/
	load_picture_and_voice("data/BradStuff/Music7.PAL.pic",NULL);
	if (SKIPPED) goto intro_end;

		/* REM: we should do some error checking here, in case anim didn't load... */
		/* and every other place anim is played */
		/* NOTE: The code insures that the last visible frame is on page1 */

		/* we need to also load in the bottom half of the large gramaphone as a seperate
			picture, first...
		*/

	LoadCompAnim(&comp_anim_data,"data/BradStuff/Grama.PAL.anim",fp_drawing->ri_page->BitMap);
	Wait(SIGBREAKF_CTRL_E);				/* wait for the music...			*/
	ResetCompAnim(&comp_anim_data,fp_drawing->ri_page->BitMap);
	new_pageflip(&comp_anim_data.colors);
	j = 0;								/* use j as a termination flag for a moment... */

	while (!SKIPPED)
	{	if (SetSignal(0L,SIGBREAKF_CTRL_E) & SIGBREAKF_CTRL_E) j = 1;

		if (j && fp_viewing == &fp_page1) break;
		NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
		new_pageflip(NULL);
	}
	FreeCompAnim(&comp_anim_data);
	if (skipped) goto intro_end;

		/* Now, insert the large gramaphone and the CDTV logo coming out of it... */

	if (gramaphone = GetPicture("data/BradStuff/GramaScroll.HAM",
		picture_palette,16,&temp_pics))
	{
		loadview(&v_null);						/* blank the display			*/

		OwnBlitter();							/* blit the gramaphone to the scene */
		blit_picture(gramaphone,&bm_main,0,0);
		DisownBlitter();

		i = gramaphone->height - OSCAN_HEIGHT - yadjust;
		FreePicList(&temp_pics);				/* free memory used by picture	*/

		wait_cop();
		LoadRGB4(vport,picture_palette,16);		/* load palette manually		*/
		scroll_title(i);

		if (delayed_skip(30)) goto intro_end;	/* wait for half a second		*/

		for (; i>=0; i--)
		{	wait_cop();
			scroll_title(i);
			WaitTOF();
			if (SKIPPED) goto intro_end;
		}

		if (delayed_skip(30)) goto intro_end;

#if 0
			/* now, insert the CDTV animation */

		if (LoadDiskAnim(&disk_anim_data,"data/BradStuff/CDTV.PAL.anim"))
		{	while (NextDiskFrame(&disk_anim_data,fp_drawing->ri_page->BitMap))
			{	wait_cop();
				new_pageflip(NULL);
				WaitTOF(); WaitTOF();
			}
			FreeDiskAnim(&disk_anim_data);
		}
#endif
	}

		/* Ghod, this code is nasty... */

	last_swap_pic = swap_pic = NULL;

	{	vp_main.RasInfo = &ri_pic;
		vp_main.UCopIns = ucl;
		ri_pic.RxOffset = ri_pic.RyOffset = 0;
		ri_pic.Next = NULL;

		view_swap_pic(CDFIN);
		logo_fx[0].result_viewport = vport;		/* set up color animation		*/
		color_list = logo_fx;					/* color animate this picture	*/

		if (delayed_skip(100)) goto intro_end;
		title_to_lores();
	}
	while (playflag) Delay(5);			/* wait for song to finish...			*/

	SuspendMusic();

		/* Show Four slabs again... */

	color_list = NULL;							/* color animate this picture	*/
	load_picture_and_voice("data/FourSlabs.Pic","data/samp.1014"); play_voice();
	load_and_play_voice("data/samp.1015");
	load_and_play_voice("data/samp.1016");
	load_and_play_voice("data/samp.1017");
	load_and_play_voice("data/samp.1018");
	if (delayed_skip(50)) goto intro_end;

	loadview(&v_null);

	color_list = NULL;
	FreePicList(&transient_pics);
	FreePicList(&temp_pics);

	goto intro_end;

		/* REM: Save this code and turn it into a killer demo... */

intro_end:
	section = 0;
/*	reset_skip();	*/				/* check current button state */

	color_list = NULL;

	/* ==================================================================== */
	/*				General Cleanup of things not needed in Menus			*/
	/* ==================================================================== */

	if (async_sample)
	{	stop_async(async_sample);
		unload_sample(async_sample);
		async_sample = NULL;
	}
	if (voice_sample)
	{	unload_sample(voice_sample);
		voice_sample = NULL;
	}

	if (channel_sample) unload_sample(channel_sample);

	SuspendMusic();
	Delay(20);
	SyncMusic(NULL,0);

/*	FilterOn(); */

		/* Get rid of the overscan and go to standard dimensions... */

	loadview(&v_null);
	remove_title();
	UnMakeBitMap(&bm_main);
	if (!MakeBitMap(&bm_main,EHB_DEPTH,STD_WIDTH,2*STD_HEIGHT))
		close_all(DERR_NO_MEMORY);
	add_tutorial();
	fp_drawing = &fp_page2; fp_viewing = &fp_page1;

	/* need to load the view... */

/*************** the beginning of the tutorial... ******************/

	vport = &vp_main;

	pulse_fx[0].result_viewport = data_fx[0].result_viewport =
		ir_fx[0].result_viewport = video_fx[0].result_viewport =
		video2_fx[0].result_viewport = video3_fx[0].result_viewport = vport;

/*	LoadRGB4(&vp_main,black_palette,LORES_COLORS); */
/*	install_cop(NULL); */
	new_pageflip(black_palette);

/*	smooth_up(8); */

	/* ==================================================================== */
	/*							Main Menu									*/
	/* ==================================================================== */

main_start:
	if (skipped == 2) goto tutorial_start;
	reset_skip();					/* check current button state */

	unless (menu_pic = GetPicture(MAIN_MENU,backdrop_palette,32,&temp_pics))
		goto menu_exit;

again1:
	if (skipped == 2) goto tutorial_start;
	reset_skip();					/* check current button state */
	blit_picture(menu_pic,fp_drawing->ri_page->BitMap,0,0);

		/* need to do the timer wait here */
		/* all thise needs to be done as a subr */

	color_list = pulse_fx;
	new_pageflip(backdrop_palette);

		/* REM: Announce the main menu... */
		/* REM: Explain how to click on buttons */

	InitRastPort(&rp_slab);
	rp_slab.BitMap = fp_viewing->ri_page->BitMap;

	if (main_explain)							/* if explanation is called for	*/
	{	main_explain = 0;

		load_and_play_voice("data/samp.2014");
		if (SKIPPED) goto noex1;
		ShowSelectBox(&rp_slab,main_selections,0);
		ShowSelectBox(&rp_slab,main_selections,1);
		ShowSelectBox(&rp_slab,main_selections,2);
	/*	ShowSelectBox(&rp_slab,main_selections,3); */
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&main_selections[3].box);

		load_and_play_voice("data/samp.2015");

		if (SKIPPED) goto noex1;
		load_voice("data/samp.2016");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&main_selections[0].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&main_selections[0].box);

		if (SKIPPED) goto noex1;
		load_voice("data/samp.2017");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&main_selections[1].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&main_selections[1].box);

		if (SKIPPED) goto noex1;
		load_voice("data/samp.2018");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&main_selections[2].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&main_selections[2].box);

		load_and_play_voice("data/samp.2019");
		load_and_play_voice("data/samp.2020");
/*
		load_and_play_voice("data/samp.2021"); */

		load_and_play_voice("data/samp.2022");
		load_and_play_voice("data/samp.2023");
		load_and_play_voice("data/samp.2024");

/*		load_and_play_voice("data/samp.2025");
		load_and_play_voice("data/samp.2026");
*/
noex1:
		;
	}

	main_selection = handle_selection(&rp_slab,main_selections, 4, main_selection);
	if (main_selection == ESCAPE_SELECT) { main_selection = 1; goto noex1; }

		/* REM: need a way to exit the program... */

	color_list = NULL;
	zoomrect(&rp_slab,&main_selections[main_selection],main_zoom,5);

		/* REM: Should we change the message if we got to the tutorial via timeout? */

	switch (main_selection) {
	case 0:										/* do intro again				*/

		/* REM: announce returning to introduction segment */

		FreePicList(&transient_pics);
		FreePicList(&temp_pics);
		reset_skip();							/* check current button state	*/
		color_list = NULL;						/* get rid of color animations	*/
		fade_to_black(backdrop_palette,16);		/* fade palette to black		*/
		loadview(&v_null);						/* black screen					*/
		remove_tutorial();						/* remove view					*/
		UnMakeBitMap(&bm_main);					/* free bitmaps					*/
		goto newdemo;							/* start intro over again		*/
	case 1:										/* do tutorials					*/
		FreePicList(&transient_pics);
		FreePicList(&temp_pics);
		goto tutorial_start;
	case 2:										/* show program demos			*/

		/* REM: announce "Here are a preview of some upcoming CDTV titles" */

		FreePicList(&transient_pics);
		FreePicList(&temp_pics);
		goto menu_exit;

		break;
	case 3:										/* show credits					*/
		main_selection = 0;						/* default for next time		*/

		FreePicList(&transient_pics);
		FreePicList(&temp_pics);

		PlaySong(5);							/* start credit music			*/

		load_picture_and_voice("data/legals02.pic",NULL);
		color_list = pulse_fx;

		reset_skip();

		InitRastPort(&rp_slab);
		rp_slab.BitMap = fp_viewing->ri_page->BitMap;
		credit_selection = handle_selection(&rp_slab,credit_selections, 2, 0);
		if (credit_selection == ESCAPE_SELECT) credit_selection = 0;

		color_list = NULL;
		zoomrect(&rp_slab,&credit_selections[credit_selection],main_zoom,5);

		if (credit_selection)
		{	load_picture_and_voice("data/credits1.pic",NULL);
			if (delayed_skip(360)) goto dofade;

			load_picture_and_voice("data/credits1A.pic",NULL);
			if (delayed_skip(200)) goto dofade;

			load_picture_and_voice("data/credits1B.pic",NULL);
			if (delayed_skip(200)) goto dofade;

			load_picture_and_voice("data/credits3.pic",NULL);
			delayed_skip(360);
		}
dofade:
		for (i=0; i<=16; i++)
		{	SetVolume(16-i);
			Delay(5);
		}
		SuspendMusic();
		SetVolume(16);
		goto main_start;

	default:
		goto again1;
	}

	goto menu_exit;

	/* ==================================================================== */
	/*							Tutorial Main Menu							*/
	/* ==================================================================== */

tutorial_start:
	reset_skip();					/* check current button state */

	menu_pic = GetPicture(TUTOR_MENU,backdrop_palette,32,&temp_pics);
	if (!menu_pic) goto menu_exit;
again:
	reset_skip();					/* check current button state */
	blit_picture(menu_pic,fp_drawing->ri_page->BitMap,0,0);

		/* need to load in the sound here, and explain what's going on */

		/* all thise needs to be done as a subr */

	color_list = pulse_fx;
	new_pageflip(backdrop_palette);

	InitRastPort(&rp_slab);
	rp_slab.BitMap = fp_viewing->ri_page->BitMap;

	if (tutorial_explain)						/* if explanation is called for	*/
	{	tutorial_explain = 0;

		if (SKIPPED) goto noex;
		load_and_play_voice("data/samp.2027");

		if (SKIPPED) goto noex;
		load_voice("data/samp.2028");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[0].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&tutorial_selections[0].box);

		if (SKIPPED) goto noex;
		load_voice("data/samp.2029");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[1].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&tutorial_selections[1].box);

		if (SKIPPED) goto noex;
		load_voice("data/samp.2030");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[2].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&tutorial_selections[2].box);

		if (SKIPPED) goto noex;
		load_voice("data/samp.2031");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[3].box);
		play_voice();
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&tutorial_selections[3].box);

		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[0].box);
		load_and_play_voice("data/samp.2032");
		load_and_play_voice("data/samp.2033");

		if (SKIPPED) goto noex;
		load_and_play_voice("data/samp.2034");
		ShowSelectBox(&rp_slab,tutorial_selections,0);
		ShowSelectBox(&rp_slab,tutorial_selections,1);
		ShowSelectBox(&rp_slab,tutorial_selections,2);
		ShowSelectBox(&rp_slab,tutorial_selections,3);
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&tutorial_selections[3].box);

		if (SKIPPED) goto noex;
		load_voice("data/samp.2035");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[0].box);
		play_voice();

		zoomrect(&rp_slab,&tutorial_selections[1],tutorial_zoom,5);
		blit_picture(menu_pic,fp_viewing->ri_page->BitMap,0,0);

		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[0].box);
		load_and_play_voice("data/samp.2036");
		load_and_play_voice("data/samp.2037");
		SetAPen(&rp_slab,0); draw_select_box(&rp_slab,&tutorial_selections[0].box);
		load_and_play_voice("data/samp.2038");
		load_and_play_voice("data/samp.2039");
		load_and_play_voice("data/samp.2040");
		load_and_play_voice("data/samp.2041");
		SetAPen(&rp_slab,16); draw_select_box(&rp_slab,&tutorial_selections[0].box);

#if 0
		if (SKIPPED) goto noex;
		load_and_play_voice("data/samp.2036");

		SetAPen(&rp_slab,0);
		draw_select_box(&rp_slab,&tutorial_selections[0].box);
		SetAPen(&rp_slab,16);
		draw_select_box(&rp_slab,&tutorial_selections[1].box);

		if (SKIPPED) goto noex;
		load_and_play_voice("data/SAMPLE008");

		zoomrect(&rp_slab,&tutorial_selections[1],tutorial_zoom,5);
		blit_picture(menu_pic,fp_viewing->ri_page->BitMap,0,0);

		if (SKIPPED) goto noex;
		load_and_play_voice("data/SAMPLE009");

		if (SKIPPED) goto noex;
		load_and_play_voice("data/SAMPLE010");

		if (SKIPPED) goto noex;
		load_voice("data/SAMPLE011");
		SetAPen(&rp_slab,16);
		draw_select_box(&rp_slab,&tutorial_selections[0].box);
		play_voice();

/*		if (SKIPPED) goto noex;
		load_and_play_voice("data/SAMPLE012"); */
#endif
noex:
		;
	}

	tutorial_selection = handle_selection(&rp_slab,tutorial_selections, 5, tutorial_selection);
	if (tutorial_selection == ESCAPE_SELECT) tutorial_selection = 4;
	color_list = NULL;

	zoomrect(&rp_slab,&tutorial_selections[tutorial_selection],tutorial_zoom,5);
	switch (tutorial_selection) {
	case 0:
		goto basic_info;
	case 1:
		goto set_the_clock;
	case 2:
		goto audio_panel_info;
	case 3:
		goto acc_info;
	case 4:
	case ESCAPE_SELECT:
		FreePicList(&transient_pics);
		FreePicList(&temp_pics);
		goto main_start;
	default:
		goto again;
	}

basic_info:

	tutorial_selection = 1;						/* default for next time		*/

	{	struct IFFPic	*picture;
		struct BitMap	*bm;

		load_picture_and_voice("data/CaddyOpen.Pic","data/samp.2001"); play_voice();
		if (SKIPPED) goto basic_info_end;

		load_and_play_voice("data/samp.2002");
		load_and_play_voice("data/samp.2003");
		load_and_play_voice("data/samp.2004");
		load_and_play_voice("data/samp.2005");
		load_and_play_voice("data/samp.2006");
		load_and_play_voice("data/samp.2007");
		load_and_play_voice("data/samp.2008");
		if (delayed_skip(100)) goto basic_info_end;

		load_picture_and_voice("data/CaddyLoad.Pic","data/samp.2009"); play_voice();
		load_and_play_voice("data/samp.2010");
		if (delayed_skip(150)) goto basic_info_end;

		load_picture_and_voice("data/CaddyInsert.Pic","data/samp.2011"); play_voice();
		load_and_play_voice("data/samp.2012");
		load_and_play_voice("data/samp.2012a");
		load_and_play_voice("data/samp.2013");

		if (delayed_skip(150)) goto basic_info_end;

	/*	load_voice("data/SAMPLE100"); play_voice(); */

	/*	pulse_fx[0].result_viewport = vport; */
		color_list = NULL;

#if 0
		/* ==================================================================== */
		/*							Caddy Animation								*/
		/* ==================================================================== */

		/* REM: load the voice here... */

		if (0)
		{	struct IFFPic *pplayer,
						*caddy,
						*caddymask,
						*doormask,
						*doormaskmask;

			pplayer   = GetPicture("data/CD-TV.Persp.Pic",backdrop_palette,32,&temp_pics);
			caddy     = GetPicture("data/Caddy.Persp.Br",NULL,0,&temp_pics);
			doormask  = GetPicture("data/Caddy.Persp.Mask",NULL,0,&temp_pics);
			caddymask = MakeMask(caddy,&temp_pics);
			doormaskmask = MakeMask(doormask,&temp_pics);

			if (pplayer && caddy && doormask && caddymask)
			{

				InvertMask(doormaskmask);
				LoadRGB4(vport,backdrop_palette,32);

				for (i=0; i<18; i++)
				{	struct BitMap *b = fp_drawing->ri_page->BitMap;

					OwnBlitter();
					blit_picture(pplayer,b,0,0);
					if (i != 17)
					{	blitmask_picture(doormaskmask,
							&caddymask->bmap,i*5-5,i-1,doormask);
						blitmask_picture(caddy,b,110-i*5,74-i,caddymask);
					}
				
					DisownBlitter();

					if (SKIPPED) goto intro_end;

					wait_cop();
					new_pageflip(NULL);

					if (i==0)			/* pause on first frame [and play voice] */
					{	if (delayed_skip(30)) goto basic_info_end;
					}
					else { wait_cop(); wait_cop(); }	/* wait an extra frame... */
				}
				FreePicList(&temp_pics);

				if (delayed_skip(30)) goto basic_info_end;
			}
		}
#endif

		/* ==================================================================== */
		/*								Player									*/
		/* ==================================================================== */

		color_list = pulse_fx;
		load_picture_and_voice("data/CDButtons/Buttons.00.Pic","data/samp.2042");
		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Power Button								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.01.Pic","data/samp.2043");
		play_voice();
		load_and_play_voice("data/samp.2044");

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Power Light									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.02.Pic","data/samp.2045");
		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Headphone Jack								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.03.Pic","data/samp.2046");
		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Disk Slot									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.04.Pic","data/samp.2047");
		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Disk Eject									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.05.Pic","data/samp.2048");
		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Data Loading Light							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.06.Pic","data/samp.2049");
		pulse_cycle[1].source_colors = pulse_yellow;
		color_list = data_fx;

		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Display Panel								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.07.Pic","data/samp.2050");
		pulse_cycle[1].source_colors = pulse_green;
		color_list = pulse_fx;
		play_voice();

			/* also check for escape... which goes to previous screen? */

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Infra-Red remote Sensor						*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.08.Pic","data/samp.2051");
		color_list = ir_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Clock Display								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.09.Pic","data/samp.2052");
		color_list = pulse_fx;
		play_voice();

		load_and_play_voice("data/samp.2053");

		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Insert Smart Card							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.10.Pic","data/samp.2054");
		play_voice();
		load_and_play_voice("data/samp.2055");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Remove Smart Card							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.11.Pic","data/samp.2056");
		play_voice();
		load_and_play_voice("data/samp.2057");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							CD Audio Controls							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.12.Pic","data/samp.2058");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Play Button									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.13.Pic","data/samp.2059");
		play_voice();
		load_and_play_voice("data/samp.2060");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Stop Button									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.14.Pic","data/samp.2061");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Skip Backward								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.15.Pic","data/samp.2062");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Skip Forward								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.16.Pic","data/samp.2063");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

#if 0
		/* ==================================================================== */
		/*							Volume Controls								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.17.Pic","data/SAMPLE117");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;
#endif

		/* ==================================================================== */
		/*							Volume Increase								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.17A.Pic","data/samp.2065");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Volume Decrease								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.18.Pic","data/samp.2066");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							CDTV / Video Select							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.19.Pic","data/samp.2067");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Reset Button								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.20.Pic","data/samp.2068");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Show Player all by itself						*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.21.Pic","data/samp.2069");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

			/* REM: insert animated transition to back */
			/* REM: insert animated transition to front */
			/* REM: insert animated transition to remote */

		/* ==================================================================== */
		/*						Show Remote										*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.00.Pic","data/samp.2070");
		play_voice();
		load_and_play_voice("data/samp.2071");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Power Button									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.01.Pic","data/samp.2072");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Volume Controls									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.02.Pic","data/samp.2073a");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						CD Audio Controls								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.03.Pic","data/samp.2074");
		play_voice();
		load_and_play_voice("data/samp.2075");
		load_and_play_voice("data/samp.2076");
		load_and_play_voice("data/samp.2077");
		load_and_play_voice("data/samp.2078");
		if (delayed_skip(100)) goto basic_info_end;

		/* REM: Need to add screens here... */

		/* ==================================================================== */
		/*						CDTV/TV Button									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.04.Pic","data/samp.2079");
		play_voice();
		if (delayed_skip(20)) goto basic_info_end;

		/* ==================================================================== */
		/*						Direction Buttons (Joystick)					*/
		/* ==================================================================== */

		load_anim_and_voice("data/CDButtons/RButtons.05.Anim","data/samp.2080");
		play_voice();		/* need to play this asynchronously... */

		for (i=1; i<16; i++)
		{	if (delayed_skip(10))
			{	FreeCompAnim(&comp_anim_data);
				goto basic_info_end;
			}
			NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
			new_pageflip(NULL);
			if (i & 1) play_sample(bink_sample);
		}
		FreeCompAnim(&comp_anim_data);

		/* ==================================================================== */
		/*						Direction Buttons (Mouse)						*/
		/* ==================================================================== */

		load_anim_and_voice("data/CDButtons/RButtons.06.Anim","data/samp.2081");
		play_voice();		/* need to play this asynchronously... */

		for (i=0; i<100; i++)
		{	if (delayed_skip(3))
			{	FreeCompAnim(&comp_anim_data);
				goto basic_info_end;
			}
			NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
			new_pageflip(NULL);
		}
		FreeCompAnim(&comp_anim_data);

		/* ==================================================================== */
		/*						Number Buttons									*/
		/* ==================================================================== */

		load_anim_and_voice("data/CDButtons/RButtons.07.Anim","data/samp.2082");
		play_voice();		/* need to play this asynchronously... */

		for (i=1; i<8; i++)
		{	if (delayed_skip(10))
			{	FreeCompAnim(&comp_anim_data);
				goto basic_info_end;
			}
			NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
			new_pageflip(NULL);
			if (i & 1) play_sample(bink_sample);
		}
		FreeCompAnim(&comp_anim_data);

		/* ==================================================================== */
		/*						Escape Buttons									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.08.Pic","data/samp.2083");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Enter Buttons									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.09.Pic","data/samp.2084");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Genloc Buttons									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.10.Pic","data/samp.2085");
		play_voice();
		load_and_play_voice("data/samp.2086");
		load_and_play_voice("data/samp.2087");
		load_and_play_voice("data/samp.2088");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Joy / Mouse Buttons								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.11.Pic","data/samp.2089");
		play_voice();
		load_and_play_voice("data/samp.2090");
		load_and_play_voice("data/samp.2091");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Select Buttons									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.12.Pic","data/samp.2092");
		play_voice();
		load_and_play_voice("data/samp.2093");
		if (delayed_skip(100)) goto basic_info_end;

		load_picture_and_voice("data/CDButtons/RButtons.13.Pic","data/samp.2094");
		play_voice();
		if (delayed_skip(10)) goto basic_info_end;

		/* ==================================================================== */
		/*						Space Invaders Pictures							*/
		/* ==================================================================== */

		load_anim_and_voice("data/CDButtons/RButtons.14.Anim","data/samp.2095");
		if (voice_sample) play_async(voice_sample);

		for (i=0; i<100; i++)
		{	if (SKIPPED)
			{	FreeCompAnim(&comp_anim_data);
				goto wait_voice;
			}
			NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
			new_pageflip(NULL);
		}
		FreeCompAnim(&comp_anim_data);

		if (voice_sample)
		{	wait_async(voice_sample);
			unload_sample(voice_sample);
			voice_sample = NULL;
		}

		/* ==================================================================== */
		/*						Show Remote Again								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.00.Pic","data/samp.2096");
		play_voice();
		load_and_play_voice("data/samp.2097");
		load_and_play_voice("data/samp.2098");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*						Icon Pictures									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/RButtons.00.Pic","data/samp.2100");
		play_voice();
		load_and_play_voice("data/samp.2101");
		load_and_play_voice("data/samp.2102");
		load_and_play_voice("data/samp.2103");
		if (delayed_skip(100)) goto basic_info_end;

			/* REM: add more pictures??? */

wait_voice:
		if (voice_sample)
		{	wait_async(voice_sample);
			unload_sample(voice_sample);
			voice_sample = NULL;
		}
	}

basic_info_end:
	make_flipmaps(EHB_DEPTH,0);
	vp_main.Modes = NULL;
	pulse_cycle[1].source_colors = pulse_green;
	color_list = NULL;
	fade_to_black(backdrop_palette,16);
	loadview(&v_null);
	FreePicList(&transient_pics);
	FreePicList(&temp_pics);
	goto tutorial_start;

audio_panel_info:
	tutorial_selection = 3;						/* default for next time		*/

	pulse_fx[0].result_viewport = vport;
	color_list = pulse_fx;

	/* ==================================================================== */
	/*						Show the Audio Panel							*/
	/* ==================================================================== */

	load_picture_and_voice("data/audiomain","data/samp.4000");
	play_voice();
	load_and_play_voice("data/samp.4001");
	load_and_play_voice("data/samp.4002");
	load_and_play_voice("data/samp.4003");

	load_picture_and_voice("data/aud-track","data/samp.4004");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-time","data/samp.4005");
	play_voice();
	load_and_play_voice("data/samp.4006");
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-indicators","data/samp.4007");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-order","data/samp.4008");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	/* REM: 4009 left out for now... */

	load_picture_and_voice("data/aud-preview","data/samp.4010");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-graphics","data/samp.4011");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-loop","data/samp.4012");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-timebutton","data/samp.4013");
	play_voice();
	load_and_play_voice("data/samp.4014");
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-rand","data/samp.4015");
	play_voice();
	if (delayed_skip(100)) goto basic_info_end;

	load_picture_and_voice("data/aud-trorder","data/samp.4016");
	play_voice();
	load_and_play_voice("data/samp.4017");
	load_and_play_voice("data/samp.4018");
	load_and_play_voice("data/samp.4019");

		/* REM: Need more pictures here.. */

	load_and_play_voice("data/samp.4020");
	load_and_play_voice("data/samp.4021");
	load_and_play_voice("data/samp.4022");
	load_and_play_voice("data/samp.4023");
	load_and_play_voice("data/samp.4024");
	load_and_play_voice("data/samp.4025");
	load_and_play_voice("data/samp.4026");
	load_and_play_voice("data/samp.4027");
	if (delayed_skip(100)) goto basic_info_end;

	goto basic_info_end;

set_the_clock:
	tutorial_selection = 2;						/* default for next time		*/

	/* ==================================================================== */
	/*						Show the Prefs Panel							*/
	/* ==================================================================== */

	load_picture_and_voice("data/PrefsPic.01","data/samp.3000");
	play_voice();
	load_and_play_voice("data/samp.3001");
	load_and_play_voice("data/samp.3002");
	load_and_play_voice("data/samp.3003");

	load_picture_and_voice("data/PrefsPic.02","data/samp.3004");
	play_voice();
	load_and_play_voice("data/samp.3005");
	load_and_play_voice("data/samp.3006");
	load_and_play_voice("data/samp.3007");

	load_picture_and_voice("data/PrefsPic.03","data/samp.3008");
	play_voice();
	load_and_play_voice("data/samp.3009");

	load_picture_and_voice("data/PrefsPic.04","data/samp.3009a");
	play_voice();

	load_picture_and_voice("data/PrefsPic.05","data/samp.3010");
	play_voice();
	delayed_skip(100);

#if 0

	{
		struct RTClock	*clockregs = (struct RTClock *)0x00dc0000;
		char			clocktime[] = "00:00:00:0:a:17:1990";
		char			textdate[32];
		char			pm;
		WORD			curpos=0,				/* position in string			*/
						edit_date=0;			/* TRUE if editing date			*/
		int				date_pixels;
		int				edit_delay = 0,
						roll = 0;
		int				hour, month;
		int				change_flag = 0;

		load_picture_and_voice("data/ClockCalender.Pic","");
		play_voice();

		/* 'Enter the date using the number keys and arrow keys on your remote
			control. Press OK when you are done.' (No ESCAPE key!!!)
		*/

		rp_text.BitMap = fp_viewing->ri_page->BitMap;
		color_list = pulse_fx;

		/* Now, set the clock... */
		/* First, we need to figure out what the current time is... */
		/* Well... I suppose we could try the AmigaDOS Date() command...
			I would like to try and get ahold of the clock directly, though...
		*/
		/* REM: Read the battery backed up clock --
			OR, read the DOS date...
		*/

			/* Note: If NO changes were made, then don't set the clock
				(else it will lose time...)
			*/

			/* REM: Check AM/PM mode... */

		clocktime[9] = '0';

		hour = (clockregs->hour_tens & 3) * 10 + (clockregs->hour_units & 15);
		month = (clockregs->month_tens & 1) * 10 + (clockregs->month_units & 15);

		if (hour > 12)
		{	hour -= 12;
			clocktime[9] = '1';
		}
		else if (clockregs->hour_tens & 4) clocktime[9] = '1';

		clocktime[0] = hour / 10 + '0';
		clocktime[1] = hour % 10 + '0';

		clocktime[3] = clockregs->minute_tens & 15 + '0';
		clocktime[4] = clockregs->minute_units & 15 + '0';

		clocktime[6] = clockregs->second_tens & 15 + '0';
		clocktime[7] = clockregs->second_units & 15 + '0';

		clocktime[13] = clockregs->day_tens & 15 + '0';
		clocktime[14] = clockregs->day_units & 15 + '0';

		clocktime[11] = month - 1;

		clocktime[18] = clockregs->year_tens & 15 + '0';
		clocktime[19] = clockregs->year_units & 15 + '0';

		if (clocktime[18] > 5)
		{	clocktime[16] = '1';
			clocktime[17] = '9';
		}
		else
		{	clocktime[16] = '2';
			clocktime[17] = '0';
		}

		/* REM: Also, can display the day of week... */

			/* For years, set the clock to 2000 if less then 50??? */

		while (TRUE)
		{	char		*monthname;

			clocktime[11] = month = (clocktime[11] + 12) % 12;

			/* if year divisible by 4, then month_table[2].days = 29;
				else month_table[month].days = 28;
			*/

			validate_long(&clocktime[16],1950,2050,roll);	/* Years			*/
			validate_digits(&clocktime[0],1,12,roll);		/* Hours			*/
			validate_digits(&clocktime[3],0,59,roll);		/* Minutes			*/
			validate_digits(&clocktime[6],0,59,roll);		/* Seconds			*/

			clocktime[9] = (clocktime[9] & 1) + '0';		/* AM/PM indicator	*/
			validate_digits(&clocktime[13],1,month_table[month].days,roll);

			SetDrMd(&rp_text,JAM2);
			SetAPen(&rp_text,15); SetBPen(&rp_text,7);		/* highlight is 19	*/
			Move(&rp_text,104,27);
			Text(&rp_text,clocktime,8);

			if (curpos == 9) SetAPen(&rp_text,19);
			if (clocktime[9] == '0') Text(&rp_text," am ",4);
			else Text(&rp_text," pm ",4);

			if (curpos < 9)
			{	int offset = TextLength(&rp_text,clocktime,curpos);
				Move(&rp_text,104+offset,27);
				SetAPen(&rp_text,19);
				Text(&rp_text,clocktime + curpos,1);
			}

			monthname = month_table[month].monthname;

			date_pixels = TextLength(&rp_text,monthname,strlen(monthname))
				+ TextLength(&rp_text,&clocktime[13],2)
				+ TextLength(&rp_text," ",1)
				+ TextLength(&rp_text,&clocktime[16],4);

			date_pixels = (320 - date_pixels)/2;

			WaitTOF();

			SetDrMd(&rp_text,JAM1);
			SetAPen(&rp_text,13);
			RectFill(&rp_text,49,73,267,92);

			Move(&rp_text,date_pixels,87);

			SetBPen(&rp_text,13);
			SetAPen(&rp_text,curpos == 11 ? 19 : 25); 
			Text(&rp_text,monthname,strlen(monthname));

			SetAPen(&rp_text,curpos == 13 ? 19 : 25); 
			Text(&rp_text,&clocktime[13],1);

			SetAPen(&rp_text,curpos == 14 ? 19 : 25); 
			Text(&rp_text,&clocktime[14],1);
			Text(&rp_text," ",1);

				/* This is the meaning of TRUE YUCK... */

			SetAPen(&rp_text,curpos == 16 ? 19 : 25);
			Text(&rp_text,&clocktime[16],1);
			SetAPen(&rp_text,curpos == 17 ? 19 : 25);
			Text(&rp_text,&clocktime[17],1);
			SetAPen(&rp_text,curpos == 18 ? 19 : 25);
			Text(&rp_text,&clocktime[18],1);
			SetAPen(&rp_text,curpos == 19 ? 19 : 25);
			Text(&rp_text,&clocktime[19],1);

			if (key || xjoy || yjoy) play_sample(bink_sample);

			if (edit_delay)
			{	edit_delay = 0;
				Delay(15);
			}

			roll = 0;

			do {
				joyread();
				key = getkey();
			} while (key == 0 && xjoy == 0 && yjoy == 0 /* && button == 0 */);

			if (xjoy || yjoy) edit_delay = TRUE;

			if ( (key >= '0' && key <= '9') ||
				key == RIGHT_ARROW ||
				xjoy == 1)
			{	if (key >= '0' && key <= '9')
				{	if (curpos != 9 && curpos != 11)
						clocktime[curpos] = key;
					change_flag = TRUE;
				}
				curpos++;
				if (clocktime[curpos] == ':') curpos++;
				else if (clocktime[curpos] == 0) curpos--;
			}
			else if (key == 'a' || key == 'A')
			{	if (curpos == 9) { clocktime[9] = '0'; change_flag = TRUE; }
			}
			else if (key == 'p' || key == 'P')
			{	if (curpos == 9) { clocktime[9] = '1'; change_flag = TRUE; }
			}
			else if (key == LEFT_ARROW || xjoy == -1)
			{	if (curpos > 0)
				{	curpos--;
					if (clocktime[curpos] == ':') curpos--;
				}
				else if (edit_date)
				{	edit_date = FALSE; curpos = 8;
				}
			}
			else if (key == UP_ARROW || yjoy == -1)
			{	roll = TRUE;
				clocktime[curpos]++;
				change_flag = TRUE;
			}
			else if (key == DOWN_ARROW || yjoy == 1)
			{	roll = TRUE;
				clocktime[curpos]--;
				change_flag = TRUE;
			}
			else if (key == ' ' || key == RETURN /* || button */) /* CONFIRM...		*/
			{	play_sample(bell_sample);
				break;
			}
			else if (key == ESCAPE) goto set_clock_exit; /* CANCEL...				*/
		}

#if 0
		if (change_flag)
		{	clockregs->second_tens = clocktime[0] - '0';
			clockregs->second_units = clocktime[1] - '0';

			clockregs->minute_tens = clocktime[3] - '0';
			clockregs->minute_units = clocktime[4] - '0';

			hour = (clocktime[5] - '0') * 10 + clocktime[6] - '0';
			pm = 0;

			if (clocktime[9] == '1') 			/* if PM						*/
			{	if (clockregs->creg_F & 0x04)	/* if 24-hour mode				*/
					hour += 12;					/* then add 12 hours			*/
				else pm = 4;					/* else set PM bit				*/
			}
			
			clockregs->hour_tens = hour/10 + pm;
			clockregs->hour_units = hour % 10;

			clockregs->day_tens = clocktime[13] - '0';
			clockregs->day_units = clocktime[14] - '0';

			month++;
			clockregs->month_tens = month / 10;
			clockregs->second_units = month % 10;

			clockregs->year_tens = clocktime[18] - '0';
			clockregs->year_units = clocktime[19] - '0';


			/* REM: Now figure out how to set the system date. At the
				very, very worst we could always execute "SetClock LOAD".
			*/
		}
#endif
	}
#endif

set_clock_exit:
	goto basic_info_end;

acc_info:

	tutorial_selection = 0;						/* default for next time		*/

	{	struct IFFPic	*picture;

		pulse_fx[0].result_viewport = vport;
		color_list = NULL;

		/* ==================================================================== */
		/*						Show the front of the player					*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Buttons.21.Pic","data/samp.5000");
		play_voice();

			/* also check for escape... which goes to previous screen? */

			/* REM: Probably make this whole thing a subroutine...? */

		if (SKIPPED) goto basic_info_end;

		if (picture = GetPicture("data/CaseFront.Br",NULL,0,&temp_pics))
		{	for (i=136; i>=65; i--)
			{	
				struct BitMap *b = fp_drawing->ri_page->BitMap;

				clear_bitmap(b);

				OwnBlitter();
				blit_picture(picture,b,21,i);
				DisownBlitter();

				if (SKIPPED) goto basic_info_end;

				wait_cop();
				new_pageflip(NULL);
			}
		}
		FreePicList(&temp_pics);

		if (SKIPPED) goto basic_info_end;

		if (load_wire(&wire_data,"data/wireframe1"))
		{	BOOL	more;
			struct BitMap *b;

			clear_bitmap(b = fp_drawing->ri_page->BitMap);
			draw_wire(&wire_data,b);
			wait_cop(); SetRGB4(vport,1,15,0,0);
			new_pageflip(NULL);

			clear_bitmap(b = fp_drawing->ri_page->BitMap);
			draw_wire(&wire_data,b);
			wait_cop();
			new_pageflip(NULL);

			do
			{	clearplane(b = fp_drawing->ri_page->BitMap,0);
				more = draw_wire(&wire_data,b);
				wait_cop();
				new_pageflip(NULL);
			} while (more);

			free_wire(&wire_data);
		}

		if (SKIPPED) goto basic_info_end;

		if (picture = GetPicture("data/CaseBack.Br",picture_palette,LORES_COLORS,&temp_pics))
		{
			for (i=65; i<=136; i++)
			{	struct BitMap *b = fp_drawing->ri_page->BitMap;

				clear_bitmap(b);

				OwnBlitter();
				blit_picture(picture,b,21,i);
				DisownBlitter();

				if (SKIPPED) goto basic_info_end;

				wait_cop();
				new_pageflip(picture_palette);
			}
		}
		FreePicList(&temp_pics);

		/* ==================================================================== */
		/*						Show the back of the box						*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.00.Pic","data/samp.5001");
		play_voice();
		load_and_play_voice("data/samp.5002");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Power Cord								*/
		/* ==================================================================== */

		color_list = pulse_fx;
		load_picture_and_voice("data/CDButtons/Ports.01.Pic","data/samp.5003");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Keyboard Port							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.02.Pic","data/samp.5004");
		play_voice();
		load_and_play_voice("data/samp.5006");
		load_and_play_voice("data/samp.5006a");
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*							Mouse / Joystick port						*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.03.Pic","data/samp.5005");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Audio Ports								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.04.Pic","data/samp.5007");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Serial Port								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.05.Pic","data/samp.5008");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Floppy Drive Port						*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.06.Pic","data/samp.5009");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Parallel Port							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.07.Pic","data/samp.5010");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Types of Video							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.07A.Pic","data/samp.5011");
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								R-F Video								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.12.Pic","data/samp.5012");
		color_list = video_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Composite Video							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.13.Pic","data/samp.5013");
		color_list = video_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								S-Video									*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.14.Pic","data/samp.5014");
		color_list = video2_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								RGB Video								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.15.Pic","data/samp.5015");
		color_list = video3_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								R-F Video Port							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.12.Pic","data/samp.5018");
		color_list = video_fx;
		play_voice();
		if (delayed_skip(40)) goto basic_info_end;

		load_picture_and_voice("data/CDButtons/Ports.12A.Pic","data/samp.5020");
		color_list = video_fx;
		play_voice();
		if (delayed_skip(60)) goto basic_info_end;

		/* ==================================================================== */
		/*								RGB Video Port							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.15.Pic","data/samp.5016");
		color_list = video3_fx;
		play_voice();
		load_and_play_voice("data/samp.5017");
		if (delayed_skip(100)) goto basic_info_end;

			/* REM: Insert channel changing switch (channel 3 or 4) */

		/* ==================================================================== */
		/*								Composite Video Port					*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.13.Pic","data/samp.5019");
		color_list = video_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								S-Video Port							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.14.Pic","data/samp.5021");
		color_list = video2_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								MIDI Ports								*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.16.Pic","data/samp.5022");
		color_list = pulse_fx;
		play_voice();
		if (delayed_skip(100)) goto basic_info_end;

		/* ==================================================================== */
		/*								Show Back Panel							*/
		/* ==================================================================== */

		load_picture_and_voice("data/CDButtons/Ports.00.Pic","data/samp.5023");
		color_list = pulse_fx;
		play_voice();
		delayed_skip(100);

		goto basic_info_end;
	}

menu_exit:
	color_list = NULL;
	remove_tutorial();
	close_all(0L);

/* no more... */

#if 0
	SuspendMusic();
	FilterOn();
#endif
}

void close_all(int errnum)
{	color_list = NULL;

#if 0
	if (errnum == DERR_NO_MEMORY) memalert();
	else if (errnum != DERR_NONE)
		Puts("Discovery had a fatal internal error!");
#endif

	FreePicList(&transient_pics);
	FreePicList(&temp_pics);
	FreePicList(&perm_pics);

	if (bink_sample) unload_sample(bink_sample);
	if (bell_sample) unload_sample(bell_sample);
	if (voice_sample) unload_sample(voice_sample);

	if (TopazFont) CloseFont(TopazFont);

	OpenWorkBench();
	DISPLAY_ON;

	if (myprocess) myprocess->pr_WindowPtr = oldWindowPtr;

	remove_null();
	free_ucop();

	UnMakeBitMap(&bm_main);

	SuspendMusic();
	FreePlayXSong();
	if (PLAY_MUSIC) FreeMusic();

	if (sprite_data) FreeMem(sprite_data,12L);

	remove_interrupt();
	wrap_device();
	wrap_gameport();
	WrapKeyConvert();
	if (TranslatorBase) CloseLibrary(TranslatorBase);
	if (IntuitionBase)
	{	unpatch_autorequest();
		CloseLibrary((struct Library *)IntuitionBase);
	}
	if (GfxBase)
	{	LoadView(oldview);
		CloseLibrary((struct Library *)GfxBase);
	}

#if 0
	if (myprocess->pr_CLI == NULL)
	{	if (olddir) CurrentDir(olddir);
		Forbid();
		ReplyMsg(&WBMsg->sm_Message);
	}
#if DEBUG
	else
	{	if (olddir) UnLock(CurrentDir(olddir));
	}
#endif
#endif

	RemIntServer(INTB_VERTB, &VertBlank);		/* remove interrupt server */

	_exit (errnum ? 10 : 0);
}

	/* handle selection of highlighted boxes. */

draw_select_box(struct RastPort *rp,struct IBox *box)
{	int					x1 = box->Left,
						x2 = box->Left + box->Width,
						y1 = box->Top,
						y2 = box->Top + box->Height;

	Move(rp,x1,y1);
	Draw(rp,x2-1,y1);
	Draw(rp,x2-1,y2-1);
	Draw(rp,x1,y2-1);
	Draw(rp,x1,y1+1);

	Draw(rp,x2-2,y1+1);
	Draw(rp,x2-2,y2-2);
	Draw(rp,x1+1,y2-2);
	Draw(rp,x1+1,y1+2);

	Draw(rp,x2-3,y1+2);
	Draw(rp,x2-3,y2-3);
	Draw(rp,x1+2,y2-3);
	Draw(rp,x1+2,y1+3);
}

ShowSelectBox(struct RastPort *rp, struct Selector *blist, int num)
{
	SetAPen(rp,16); draw_select_box(rp,&blist[num].box);
	Delay(30);
	SetAPen(rp,0); draw_select_box(rp,&blist[num].box);
}

int handle_selection(struct RastPort *rp, struct Selector *blist, int count, int init)
{	int 				i, key;
	int					selection = init;

	SetAPen(rp,0);
	for (i=0; i<count; i++)
	{	draw_select_box(rp,&blist[i].box);
	}
	SetAPen(rp,16);
	draw_select_box(rp,&blist[selection].box);

	clearkey();
	/* button = 0; */

	handler_data.timeout = (TIME_TO_WAIT);
	key = 0;

	while (/* button == 0 && */ handler_data.timeout != 0 && key != ' ' &&
		key != RETURN)
	{	joyread();
liner:	if (xjoy || yjoy)
		{
			SetAPen(rp,0); draw_select_box(rp,&blist[selection].box);
			if (xjoy < 0) selection = blist[selection].next[2];
			else if (xjoy > 0) selection = blist[selection].next[3];
			else if (yjoy < 0) selection = blist[selection].next[0];
			else if (yjoy > 0) selection = blist[selection].next[1];
			SetAPen(rp,16); draw_select_box(rp,&blist[selection].box);
			handler_data.timeout = (TIME_TO_WAIT);
			Delay(10);
		}
		key = getkey();
		if (key == LEFT_ARROW) { xjoy = -1; goto liner; }
		if (key == RIGHT_ARROW) { xjoy = 1; goto liner; }
		if (key == UP_ARROW) { yjoy = -1; goto liner; }
		if (key == DOWN_ARROW) { yjoy = 1; goto liner; }
	/*	if (key == HELP_KEY) { selection = HELP_SELECT; break; } */
		if (key == ESCAPE) { selection = ESCAPE_SELECT; break; }
	}
	play_sample(bell_sample);
	reset_skip();					/* check current button state */
	return selection;
}

zoomrect(struct RastPort *rp, struct Selector *s, WORD *colorlist, int numcolors)
{	struct IBox			*box = &s->box;
	int					x1 = box->Left,
						x2 = box->Left + box->Width,
						y1 = box->Top,
						y2 = box->Top + box->Height;
	int					i,j,color;
	WORD				x1_list[17],
						x2_list[17],
						y1_list[17],
						y2_list[17];

		/* now, we want to interpolate these values, in about 16 steps, until
			we get to the edge... */

	for (i=0; i<=16; i++)
	{	x1_list[i] = x1 * (16 - i) / 16;
		y1_list[i] = y1 * (16 - i) / 16;
		x2_list[i] = ((STD_WIDTH - x2) * i) / 16 + x2;
		y2_list[i] = ((STD_HEIGHT - y2) * i) / 16 + y2;
	}

		/* REM: We might also fade the palette while this is going on... */

	for (i = -numcolors; i < 16; i++)
	{	for (j=i,color = 0; j<i+numcolors;j++,color++)
		{	if (j < -1 || j >= 16) continue;

			SetAPen(rp,colorlist[color]);
			if (j == -1) draw_select_box(rp,box);
			else
			{	int x1a = x1_list[j+1];
				int x2a = x2_list[j+1];
				int y1a = y1_list[j+1];
				int y2a = y2_list[j+1];

				x1 = x1_list[j];
				x2 = x2_list[j];
				y1 = y1_list[j];
				y2 = y2_list[j];
				
				if (y1a < y1) RectFill(rp, x1a, y1a, x2a-1, y1-1  );
				if (y2 < y2a) RectFill(rp, x1a, y2,  x2a-1, y2a-1 );
				if (x1a < x1) RectFill(rp, x1a, y1,  x1-1,  y2-1  );
				if (x2 < x2a) RectFill(rp, x2,  y1,  x2a-1, y2-1  );
			}
		}
/*		Delay(2); */
	}
}

#if 0
ozoomrect(struct RastPort *rp, struct Selector *s, WORD *colorlist, int numcolors)
{	struct IBox			*box = &s->box;
	int					x1 = box->Left,
						x2 = box->Left + box->Width,
						y1 = box->Top,
						y2 = box->Top + box->Height;
	int					i,j,color;
	WORD				x1_list[17],
						x2_list[17],
						y1_list[17],
						y2_list[17];

		/* now, we want to interpolate these values, in about 16 steps, until
			we get to the edge... */

	for (i=0; i<=16; i++)
	{	x1_list[i] = x1 * (16 - i) / 16;
		y1_list[i] = y1 * (16 - i) / 16;
		x2_list[i] = ((OSCAN_WIDTH - x2) * i) / 16 + x2;
		y2_list[i] = ((OSCAN_HEIGHT - y2) * i) / 16 + y2;
	}

		/* REM: We might also fade the palette while this is going on... */

	for (i = -numcolors; i < 16; i++)
	{	for (j=i,color = 0; j<i+numcolors;j++,color++)
		{	if (j < -1 || j >= 16) continue;

			SetAPen(rp,colorlist[color]);
			if (j == -1) draw_select_box(rp,box);
			else
			{	int x1a = x1_list[j+1];
				int x2a = x2_list[j+1];
				int y1a = y1_list[j+1];
				int y2a = y2_list[j+1];

				x1 = x1_list[j];
				x2 = x2_list[j];
				y1 = y1_list[j];
				y2 = y2_list[j];
				
				if (y1a < y1) RectFill(rp, x1a, y1a, x2a-1, y1-1  );
				if (y2 < y2a) RectFill(rp, x1a, y2,  x2a-1, y2a-1 );
				if (x1a < x1) RectFill(rp, x1a, y1,  x1-1,  y2-1  );
				if (x2 < x2a) RectFill(rp, x2,  y1,  x2a-1, y2-1  );
			}
		}
/*		Delay(2); */
	}
}

int validate_digits(char *s,int min,int max,int roll)
{	int nval = (s[0] - '0') * 10 + s[1] - '0';

		/* Q: how to do rollover? */

	if (roll)
	{	if (nval > max) nval = min;
		else if (nval < min) nval = max;
	}
	else
	{	if (nval > max) nval = max;
		else if (nval < min) nval = min;
	}

	s[0] = nval / 10 + '0';
	s[1] = nval % 10 + '0';

	return nval;
}

int validate_long(char *s,int min,int max,int roll)
{	int nval = (s[0] - '0') * 1000 +
			   (s[1] - '0') * 100 +
			   (s[2] - '0') * 10 +
			   (s[3] - '0') * 1;

	if (roll)
	{	if (nval > max) nval = min;
		else if (nval < min) nval = max;
	}
	else
	{	if (nval > max) nval = max;
		else if (nval < min) nval = min;
	}

	s[3] = nval % 10 + '0'; nval /= 10;
	s[2] = nval % 10 + '0'; nval /= 10;
	s[1] = nval % 10 + '0'; nval /= 10;
	s[0] = nval % 10 + '0';

	return nval;
}
#endif

view_swap_pic(char *picname)
{	int					normal_height = (GfxBase->DisplayFlags & PAL) ? OSCAN_HEIGHT : NTSC_HEIGHT;
	struct cprlist		*lof,*shf;
	UWORD				temp_palette[32];

	if (SKIPPED) return;

/*	if (picname) */
		swap_pic = GetPicture(picname,temp_palette,32,&temp_pics);
/*	else swap_pic = CatGetPicture(temp_palette,32,&temp_pics); */

	unless (swap_pic)
	{	putcon("Couldn't load ");
		putcon(picname);
		putcon("\n");
		return;
	}

	vp_main.Modes = lastcamg & (LACE|HAM|EXTRA_HALFBRITE);
	if (lastcamg & LACE) { normal_height *= 2; }

	vp_main.DHeight =
		MIN(swap_pic->height,(lastcamg & LACE) ? (OSCAN_HEIGHT * 2) : OSCAN_HEIGHT);
	vp_main.DWidth = MIN(swap_pic->width,OSCAN_WIDTH);
	vp_main.DyOffset = (normal_height - swap_pic->height) / 2;
	v.DxOffset = xoffset - (swap_pic->width - OSCAN_WIDTH) / 2;

	ri_pic.BitMap = &swap_pic->bmap;

	lof = v.LOFCprList;
	shf = v.SHFCprList;
	v.LOFCprList = v.SHFCprList = NULL;

	color_list = NULL;
	CopyMem(temp_palette,backdrop_palette,sizeof backdrop_palette);

	MakeVPort( &v, &vp_main );
	MrgCop( &v );
	LoadRGB4(&vp_main,backdrop_palette,16);
	loadview(&v);

	if (lof) FreeCprList(lof);
	if (shf) FreeCprList(shf);

	FreePicture(last_swap_pic);
	last_swap_pic = swap_pic;
}

load_picture_and_voice(char *picname, char *voicename)
{	if (SKIPPED) return;
	if (voicename && *voicename) load_voice(voicename);
	else voice_sample = NULL;

	if (unpackpic(picname,fp_drawing->ri_page->BitMap,picture_palette))
	{	CopyMem(picture_palette,backdrop_palette,sizeof backdrop_palette);
		vp_main.Modes = lastcamg & (HAM|EXTRA_HALFBRITE);
		new_pageflip(backdrop_palette);
	}
}

load_anim_and_voice(char *picname, char *voicename)
{	if (SKIPPED) return;
	if (voicename && *voicename) load_voice(voicename);
	else voice_sample = NULL;

	if (LoadCompAnim(&comp_anim_data,picname,fp_drawing->ri_page->BitMap))
	{	vp_main.Modes = lastcamg & (HAM|EXTRA_HALFBRITE);
		ResetCompAnim(&comp_anim_data,fp_drawing->ri_page->BitMap);
		CopyMem(&comp_anim_data.colors,backdrop_palette,sizeof backdrop_palette);
		CopyMem(&comp_anim_data.colors,picture_palette,sizeof backdrop_palette);
		new_pageflip(backdrop_palette);
	}
}

load_voice(char *voicename)
{	if (SKIPPED) return;
	if (voicename) voice_sample = load_sample(voicename);
	else voice_sample = NULL;
	return (voice_sample != 0);
}

load_and_play_voice(char *voicename)
{	if (SKIPPED) return;
	if (voicename)
	{	voice_sample = load_sample(voicename);
		play_voice();
	}
	else voice_sample = NULL;
}

play_voice()
{	if (SKIPPED) return;
	if (voice_sample)
	{	Delay(40);
		play_sample(voice_sample);
		unload_sample(voice_sample);
		voice_sample = NULL;
	}
}

play_sound_and_abrush(char *ab_name, char *samp_name, char *tname, int xpos, int ypos)
{	struct BitMap *animb;

	if (!unpackpic("data/FourSlabs.Pic",fp_drawing->ri_page->BitMap,backdrop_palette))
		return;
	new_pageflip(backdrop_palette);

	LoadAnim(&anim_data,ab_name);
	animb = ResetAnim(&anim_data,2);			/* continuous... */

		/* repeat until sound finished... */

	if (load_voice(samp_name)) play_async(voice_sample);

		/* sync up the dbuffered pages... */

	BltBitMap(fp_viewing->ri_page->BitMap,0,0,fp_drawing->ri_page->BitMap,0,0,
		OSCAN_WIDTH,OSCAN_HEIGHT, 0xC0, 0xFF, NULL);

	while (!skipped)
	{	if (voice_sample && check_async(voice_sample)) break;

		BltBitMap(animb,0,0,fp_drawing->ri_page->BitMap,xpos,ypos,
			anim_data.width,anim_data.current->bm.Rows, 0xC0, 0xFF, NULL);
		Delay(3);
		wait_cop();
		new_pageflip(NULL);
		animb = NextAnimFrame(&anim_data);
	}
	FreeAnim(&anim_data);

	if (voice_sample)
	{	wait_async(voice_sample);
		unload_sample(voice_sample);
		voice_sample = NULL;
	}

	if (skipped) return;

	load_anim_and_voice(tname,NULL);
	for (;;)
	{	Delay(3);
		NextCompFrame(&comp_anim_data,fp_drawing->ri_page->BitMap);
		new_pageflip(NULL);
		if (comp_anim_data.current == NULL) break;
	}
	FreeCompAnim(&comp_anim_data);
}

free_ucop()
{	struct ViewPort vp;

	if (ucl)
	{	InitVPort(&vp);
		vp.UCopIns = ucl;
		FreeVPortCopLists(&vp);
		ucl = NULL;
	}
}

clear_main()
{	struct RastPort		temp_rp;

	InitRastPort(&temp_rp);
	temp_rp.BitMap = &bm_main;
	SetRast(&temp_rp,0);
}

clear_bitmap(struct BitMap *b)
{	int i;

	for (i=0; i<b->Depth; i++) clearplane(b,i);
}

	/* create the bitmaps BM_FIRST and BM_SECOND from the main bitmap,
		except use the specified depth (don't actually allocate anything new).
	*/

int overscan = TRUE;

make_flipmaps(int depth, int lace)
{
	if (overscan)
	{	InitBitMap(&bm_first,depth,OSCAN_WIDTH,OSCAN_HEIGHT * (lace ? 2 : 1));
		InitBitMap(&bm_second,depth,OSCAN_WIDTH,OSCAN_HEIGHT * (lace ? 2 : 1));
	}
	else
	{	InitBitMap(&bm_first,depth,STD_WIDTH,STD_HEIGHT * (lace ? 2 : 1));
		InitBitMap(&bm_second,depth,STD_WIDTH,STD_HEIGHT * (lace ? 2 : 1));
	}

	for (i=0; i<depth; i++)
	{	bm_first.Planes[i] = bm_main.Planes[i];
		bm_second.Planes[i] = (char *)(bm_main.Planes[i]) +
			bm_first.BytesPerRow * bm_first.Rows;
	}
	if (lace) bm_second = bm_first;
}

	/* add the main viewport and set up for page flipping... */

add_title()
{	InitView(&v);
	InitVPort(&vp_main);

	v.DxOffset = xoffset;
	v.DyOffset = yoffset;
	v.ViewPort = &vp_main;
	v.Modes = LACE;

	vp_main.Next = NULL;
	vp_main.DWidth = OSCAN_WIDTH;
	vp_main.DHeight = (GfxBase->DisplayFlags & PAL) ? OSCAN_HEIGHT : NTSC_HEIGHT;
	vp_main.DxOffset = vp_main.DyOffset = 0;
	vp_main.RasInfo = &ri_page1;
	vp_main.Modes = NULL;

	overscan = TRUE;
	make_flipmaps(EHB_DEPTH,0);
	ri_page1.BitMap = &bm_first;
	ri_page2.BitMap = &bm_second;
	
	ri_page1.RxOffset = ri_page2.RxOffset = 0;
	ri_page1.RyOffset = ri_page2.RyOffset = yadjust;
	ri_page1.Next = ri_page2.Next = NULL;

	fp_page1.ri_page = &ri_page1;
	fp_page2.ri_page = &ri_page2;

		/* (init color table) */

	vp_main.ColorMap = GetColorMap(LORES_COLORS);
	LoadRGB4(&vp_main,black_palette,LORES_COLORS);

	vp_main.UCopIns = ucl;

	return 0;
}

remove_title()
{	delete_viewport(&vp_main);
	delete_view(&v);
}

	/* add the main viewport and set up for page flipping... */

add_tutorial()
{	InitView(&v);
	InitVPort(&vp_main);

	v.DxOffset = xoffset + (OSCAN_WIDTH - STD_WIDTH) / 2;
	v.ViewPort = &vp_main;
	v.Modes = LACE;

	vp_main.Next = NULL;
	vp_main.DWidth = STD_WIDTH;
	vp_main.DHeight = STD_HEIGHT;
	vp_main.DxOffset = vp_main.DyOffset = 0;
	vp_main.RasInfo = &ri_page1;
	vp_main.Modes = NULL;

	overscan = FALSE;
	make_flipmaps(EHB_DEPTH,0);
	ri_page1.BitMap = &bm_first;
	ri_page2.BitMap = &bm_second;
	
	ri_page1.RxOffset = ri_page2.RxOffset = 0;
	ri_page1.RyOffset = ri_page2.RyOffset = 0;
	ri_page1.Next = ri_page2.Next = NULL;

	fp_page1.ri_page = &ri_page1;
	fp_page2.ri_page = &ri_page2;

		/* (init color table) */

	vp_main.ColorMap = GetColorMap(LORES_COLORS);
	LoadRGB4(&vp_main,titlecolors,LORES_COLORS);

	vp_main.UCopIns = ucl;

	return 0;
}

remove_tutorial()
{	delete_viewport(&vp_main);
	delete_view(&v);
}

#if 0
	/* change the title viewport to ExtraHalfBrite */

title_to_ehb()
{	make_flipmaps(EHB_DEPTH,0);
	vp_main.Modes = EXTRA_HALFBRITE;
	vp_main.DHeight = (GfxBase->DisplayFlags & PAL) ? OSCAN_HEIGHT : NTSC_HEIGHT;
}

title_to_ehb_lace()
{	make_flipmaps(EHB_DEPTH,1);
	vp_main.Modes = EXTRA_HALFBRITE | LACE;
	vp_main.DHeight = (GfxBase->DisplayFlags & PAL) ? OSCAN_HEIGHT*2 : NTSC_HEIGHT*2;
}

title_to_ham()
{	make_flipmaps(EHB_DEPTH,0);
	vp_main.Modes = HAM;
	vp_main.DHeight = (GfxBase->DisplayFlags & PAL) ? OSCAN_HEIGHT : NTSC_HEIGHT;
}
#endif

title_to_lores()
{	make_flipmaps(EHB_DEPTH,0);
	v.DxOffset = xoffset;
	v.DyOffset = yoffset;
	vp_main.Modes = NULL;
	vp_main.DyOffset = 0;
	vp_main.DHeight = (GfxBase->DisplayFlags & PAL) ? OSCAN_HEIGHT : NTSC_HEIGHT;
	vp_main.DWidth = OSCAN_WIDTH;
	vp_main.RasInfo = fp_viewing->ri_page;
}

	/* Flip pages between the two new pages */

new_pageflip(UWORD *newcolors)
{	struct fpage *temp;
	struct cprlist *lof,*shf;

	temp = fp_drawing;			/* swap RasInfo pointers */
	fp_drawing = fp_viewing;
	fp_viewing = temp;

	vp_main.RasInfo = temp->ri_page;

	lof = v.LOFCprList;
	shf = v.SHFCprList;
	v.LOFCprList = v.SHFCprList = NULL;

	MakeVPort( &v, &vp_main );
	MrgCop( &v );
	if (newcolors)
		LoadRGB4(&vp_main,newcolors,LORES_COLORS);
	loadview(&v);

	if (lof) FreeCprList(lof);
	if (shf) FreeCprList(shf);
}

#if 0
install_cop(struct UCopList *cop)
{	struct cprlist *lof,*shf;

	vport->UCopIns = cop ? cop : ucl;

	lof = v.LOFCprList;
	shf = v.SHFCprList;
	v.LOFCprList = v.SHFCprList = NULL;

	MakeVPort( &v, &vp_main );
	MrgCop( &v );
	loadview(&v);

	if (lof) FreeCprList(lof);
	if (shf) FreeCprList(shf);
}
#endif

remake_title()
{	MakeVPort( &v, &vp_main );
	MrgCop( &v );
	loadview(&v);
}

	/* REM - make these void. */

delete_viewport(struct ViewPort *vp)
{	if (vp)
	{	if (vp->ColorMap)
		{	FreeColorMap(vp->ColorMap);
			vp->ColorMap = NULL;
		}
		vp->UCopIns = NULL;					/* please don't deallocate this one */
		FreeVPortCopLists(vp);
	}
}

delete_view(struct View *v)
{	if (v)
	{	if (v->LOFCprList) FreeCprList(v->LOFCprList);
		if (v->SHFCprList) FreeCprList(v->SHFCprList);
		v->LOFCprList = v->SHFCprList = 0;
	}
}

	/* set the vertical scroll position of the title screen to n */

scroll_title(int n)
{	struct cprlist *lof,*shf;

	fp_viewing->ri_page->RyOffset = n + yadjust;

	lof = v.LOFCprList;
	shf = v.SHFCprList;
	v.LOFCprList = v.SHFCprList = NULL;

	MakeVPort( &v, &vp_main );
	MrgCop(&v);
	loadview(&v);

	if (lof) FreeCprList(lof);
	if (shf) FreeCprList(shf);
}

extern char keytrans[];

struct MsgPort		*inputDevPort=NULL;
struct IOStdReq		*inputRequestBlock=NULL;
struct Interrupt	handlerStuff;
short				input_device_open=FALSE;

add_device()
{	SHORT error;
#if 0
	void HandlerInterface();
#endif

	unless (inputDevPort = CreatePort(0,0)) return FALSE;
	unless (inputRequestBlock = CreateStdIO(inputDevPort)) goto exitit;
	if (error = OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
		goto exitit;

	input_device_open = TRUE;

	handlerStuff.is_Data = (APTR)&handler_data;
	handlerStuff.is_Code = (void (*)())HandlerInterface;
	handlerStuff.is_Node.ln_Pri = 51;

	inputRequestBlock->io_Command = IND_ADDHANDLER;
	inputRequestBlock->io_Data = (APTR)&handlerStuff;

#if 0
		/* disable handler joystick reading */
	handler_data.joydown |= BUTTON_PRESSED;
#endif

	DoIO((struct IORequest *)inputRequestBlock);
	handler_data.laydown = handler_data.pickup = 0;
	return TRUE;

exitit:
	wrap_device();
	return FALSE;
}

wrap_device()
{	if (inputRequestBlock)
	{	if (input_device_open)
		{	inputRequestBlock->io_Command = IND_REMHANDLER;
			inputRequestBlock->io_Data = (APTR)&handlerStuff;
			DoIO((struct IORequest *)inputRequestBlock);

			CloseDevice((struct IORequest *)inputRequestBlock);
		}
		DeleteStdIO(inputRequestBlock);
	}
	if (inputDevPort) DeletePort(inputDevPort);
}

int getkey()
{	int key;
	if (handler_data.pickup == handler_data.laydown) return 0;

	key = handler_data.keybuf[handler_data.pickup++];
	handler_data.pickup &= 127;
	if (key == HELP_KEY) return key;
	if (key == RETURN || key == BACKSPACE || key == ESCAPE) return key;
	if (key >= UP_ARROW && key <= LEFT_ARROW) return key;
	if (key >= ' ' && key <= 0x7e) return toupper(key);
	return 0;
}

clearkey()
{
	while (getkey()) ;
}

/* static WORD user_button = 0; */

#if 0
user_skip()
{
/*	int		key; */

/*	clearkey(); */
	return skipped;

/*
	if (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
		return skipped = 1;

	while (key = getkey())
	{
		if (key == ' ' || key == RETURN || key == ESCAPE) return skipped = 1;
	}
	return 0;
*/
}
#endif

BOOL delayed_skip(UWORD ticks)
{

/*	BOOL skip = 0;

	if (skipped) return TRUE; */

	/* may want to adjust ticks by vblank frequency */
	ticks = ticks * SysBase->VBlankFrequency / 50;

	while (ticks-- && !skipped) wait_cop();

	return skipped;
}

reset_skip()
{
	clearkey();
	skipped = FALSE;
	SetSignal(0L,SIGBREAKF_CTRL_C);
}

#if 0
int testkey()
{	int key;
	if (handler_data.pickup == handler_data.laydown) return 0;

	key = handler_data.keybuf[handler_data.pickup];
	if (key == HELP_KEY) return key;
	if (key == RETURN || key == BACKSPACE) return key;
	if (key >= UP_ARROW && key <= LEFT_ARROW) return key;
#if 0
	if ((UBYTE)key >= (UBYTE)S_UP_ARROW &&
		(UBYTE)key <= (UBYTE)S_LEFT_ARROW) return key;
	if (key >= ' ' && key <= 0x7e) return toupper(key);
	/* if (key >= (char)0xa0 && key <= (char)0xff) return toupper(key); */
#ifdef DEBUG
	if (key >= (char)FUNKEY1 && key <= (char)FUNKEY10) return key;
#endif
#endif
	return 0;
}
#endif

#if 0
fade_from_black(UWORD *palette, int steps)
{	fade_palettes(black_palette,palette,0x10000L/steps);
}
#endif

fade_to_black(UWORD *palette, int steps)
{	fade_palettes(palette,black_palette,0x10000L/steps);
}

#if 0
fadeup(int n)
{	for (i=0; i<=160; i+=n)
	{	fade_map(i);
		WaitTOF(); /* wait_cop(); */
	}
}

smooth_up(int n)
{	struct cprlist *lof,*shf;

	for (i=0; i<=160; i+=n)
	{
		lof = v.LOFCprList;
		shf = v.SHFCprList;
		v.LOFCprList = v.SHFCprList = NULL;

		MakeVPort(&v,vport);
		MrgCop(&v);
		fade_map(i);

		loadview(&v);

		if (lof) FreeCprList(lof);
		if (shf) FreeCprList(shf);
	}
}

fadedn(int n)
{	for (i=160; i>=0; i-=n)
	{	fade_map(i);
		WaitTOF(); /* wait_cop(); */
	}
}
#endif

loadview(v)	struct View *v;
{
	/* if (v == &v_null) DISPLAY_OFF; */
	LoadView(myView = v);
	WaitTOF();
	/* if (v != &v_null) DISPLAY_ON; */
}

add_null()
{	InitView(&v_null);
	InitVPort(&vp_null);

	v_null.DxOffset = xoffset;
	v_null.DyOffset = yoffset;
	v_null.ViewPort = &vp_null;

	vp_null.Next = NULL;
	vp_null.DWidth = 320;
	vp_null.DHeight = 20;
	vp_null.DxOffset = vp_null.DyOffset = 0;
	vp_null.RasInfo = &ri_null;

	ri_null.BitMap = &bm_null;
	ri_null.RxOffset = ri_null.RyOffset = 0;
	ri_null.Next = NULL;

	if (!(vp_null.ColorMap = GetColorMap(2))) return 1;

	SetRGB4(&vp_null,0,0,0,0);
	SetRGB4(&vp_null,1,0,0,0);

	if (!MakeBitMap(&bm_null,1,320,5)) return 1;
	vp_null.UCopIns = ucl;

	MakeVPort( &v_null, &vp_null );
	MrgCop(&v_null);

	return 0;
}

remove_null()
{
	UnMakeBitMap(&bm_null);
	delete_viewport(&vp_null);
	delete_view(&v_null);
}

extern struct UCopList		*ucl;			/* pointer to user copper list	*/

init_ucop()
{	struct Custom *regs = (struct Custom *)0x00dff000;

	if ( !(ucl = AllocMem(sizeof *ucl,MEMF_CLEAR|MEMF_PUBLIC)) )
		return 0;

	CWAIT(ucl,PAGE_HEIGHT-2,0);
	CMOVE(ucl,regs->intreq,0x8010);
	CEND(ucl);
	return 1;
}

joyread()
{	extern char		record, *joybuf;
	extern ULONG	joybufsize,ji;
	extern struct in_work handler_data;
	BYTE			recbyte;

	xjoy = handler_data.xjoy;
	yjoy = handler_data.yjoy;
	/* button = ((handler_data.joydown & JOY_FIRE) != 0); */
}

/* TEST CODE */

void build_slab(struct IFFPic *newpic, int border, int combsize)
{	int					width = newpic->width,
						height = newpic->height,
						depth = newpic->bmap.Depth;
	int					mindim,
						border_size;
	int					plane;
	register			struct Custom *Custom = (struct Custom *)0x00dff000;
	struct IFFPic		*contents;

		/* set up the blitter.... */

	OwnBlitter();
	WaitBlit();

	pl = bm_draw->Planes;

	/*	A = source material
		B = mask... (later)
		C = dest.
		D = dest.
	*/

	Custom->bltamod = stone2->bmap.BytesPerRow - newpic->bmap.BytesPerRow;
	Custom->bltcmod = Custom->bltdmod = 0;
	Custom->bltafwm = Custom->bltalwm = ~0;
	Custom->bltcon0 = SRCA|DEST|A_TO_D;
	Custom->bltcon1 = 0;

	for(plane = 0; plane<depth; plane++)
	{	WaitBlit();
		Custom->bltapt = (APTR)(stone2->bmap.Planes[plane]);
		Custom->bltdpt = Custom->bltcpt = (APTR)(newpic->bmap.Planes[plane]);
		Custom->bltsize = (newpic->bmap.BytesPerRow >> 1) | (height << HSIZEBITS);
	}

/*	BltBitMap(&stone2->bmap,0,0, &newpic->bmap,0,0,
		width,height,
		0xC0, 0xFF, NULL);
*/

	DisownBlitter();

	if (border)
	{
		/* blit the top-edge highlight. */

		BltBitMap(&stone1->bmap,0,0, &newpic->bmap,0,0,
			width,border,
			0xC0, 0xFF, NULL);

			/* blit the bottom edge highlight... */

		BltBitMap(&stone3->bmap,0,height-border, &newpic->bmap,0,height-border,
			width,border,
			0xC0, 0xFF, NULL);

			/* blit the left edge highlight. */
			/* (USE THE MASK) */

		BltBitMap(&stone1->bmap,0,0, &newpic->bmap,0,0,
			border,height,
			0xC0, 0xFF, NULL);

			/* blit the right edge highlight... */

		BltBitMap(&stone3->bmap,width-border,0, &newpic->bmap,width-border,0,
			border,height,
			0xC0, 0xFF, NULL);

			/* set up a temp rp and draw in the bottom lines... */

		rp_slab.BitMap = &newpic->bmap;
		SetAPen(&rp_slab,8);
		Move(&rp_slab,0,height-1);
		Draw(&rp_slab,width-1,height-1);
		Draw(&rp_slab,width-1,0);
	}

		/* draw in contents slab */

	if (combsize < 0)
	{	return;
	}

	contents = comb_pics[combsize];

	if (contents && contents->width < newpic->width && comb_heights[combsize] < newpic->height)
	{	int				wdiff,
						hdiff,
						offset;

		wdiff = newpic->width - contents->width;
		hdiff = newpic->height - comb_heights[combsize];

		BltBitMap(&contents->bmap,0,comb_offset[combsize],
			&newpic->bmap,wdiff/2,hdiff/2,
			contents->width,comb_heights[combsize],
		0xC0, 0xFF, NULL);

		comb_offset[combsize] += comb_heights[combsize];
		if (comb_offset[combsize] >= contents->height)
			comb_offset[combsize] = 0;
	}
}

blit_centered(struct IFFPic *source, struct BitMap *dest)
{	blit_picture(
		source,
		dest,
		(OSCAN_WIDTH-source->width)/2,
		(OSCAN_HEIGHT-source->height)/2);
}

blit_centered_lace(struct IFFPic *source, struct BitMap *dest)
{	blit_picture(
		source,
		dest,
		(OSCAN_WIDTH-source->width)/2,
		(OSCAN_HEIGHT*2-source->height)/2);
}

putcon(char *str)
{	AFILE o = Output();

	if (o) Write(o,str,strlen(str));
}
