scummvm/sword2/controls.cpp
Torbjörn Andersson 8277c6cb79 The graphics detail settings partially work now. They only affect how
sprites are drawn, but I think that's how it should be.

1: No bells or whistles.
2: This setting adds sprite blending, e.g. the smoke at the docks or the
   display cases at the Glease Gallery.
3: This setting adds light map support, e.g. when walking under the shack
   at the docks.
4: This setting adds better scaling algorithms.

The first three settings should work fine now. In fact, the third setting
is what we used to implement. The fourth setting still needs work and
testing. I've added code for downscaling case, but frankly I'm not
convinced the result is any better than with the simpler scaler. I usually
can't even tell the difference.

Of course, my translation of the original code could very well be buggy.

svn-id: r9867
2003-08-26 06:53:00 +00:00

2817 lines
78 KiB
C++

/* Copyright (C) 1994-2003 Revolution Software Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*/
//-----------------------------------------------------------------------------------------------------------------------
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
//#include "src\driver96.h"
#include "stdafx.h"
#include "build_display.h"
#include "console.h"
#include "controls.h"
#include "debug.h"
#include "defs.h"
#include "header.h"
#include "interpreter.h"
#include "layers.h"
#include "logic.h"
#include "maketext.h" // for font resource variables
#include "mem_view.h"
#include "memory.h"
#include "mouse.h"
#include "protocol.h"
#include "resman.h"
#include "router.h"
#include "save_rest.h"
#include "sound.h" // for FN_stop_music()
#include "startup.h"
#include "sword2.h"
//-----------------------------------------------------------------------------------------------------------------------
#define WINDOW_RES 2016
#define MAX_STRING_LEN 64 // 20 was too low; better to be safe ;)
#define CHARACTER_OVERLAP 2 // overlap characters by 3 pixels
//-----------------------------------------------------------------------------------------------------------------------
void Create_surface_image(_spriteInfo *sprite, uint8 **surface, uint32 res, uint32 x, uint32 y, uint32 pc);
void Build_surfaces(void);
void Build_chr_surfaces(void);
void Kill_chr_surfaces(void);
void Kill_surfaces(void);
void Renew_surfaces(void);
void Engine_string(uint32 x, uint32 y, uint32 res, uint8 **surface_list, uint8 *buf);
void Kill_mini_surfaces(void);
void Build_mini_surfaces(void);
uint32 Generic_mini_control(uint32 text_id);
uint32 Pixel_text_length(uint8 *buf, uint32 res);
void Control_error(char* text);
//-----------------------------------------------------------------------------------------------------------------------
#define WINDOW_X 0
#define REST_X 84
#define REST_Y 40
#define SLAB_X (REST_X+30)
#define SLAB_Y (REST_Y+32)
#define REST_BUT_X 130
#define REST_BUT_Y 377
#define CAN_BUT_X 350
#define CAN_BUT_Y 377
#define UP_BUT_X 516
#define UP_BUT_Y 85
#define DOWN_BUT_X 516
#define DOWN_BUT_Y 329
#define ZUP_BUT_Y 85-20
#define ZDOWN_BUT_Y 329+21
#define SLAB_Y_SPACING 35
#define QUIT_X 203
#define QUIT_Y 104
#define OPTION_X 45
#define OPTION_Y 40
#define OPTION_W 552
#define OPT_BUT_W 53
#define OPT_BUT_H 32
#define OPT_OK_X (OPTION_X+(OPTION_W/3)-(OPT_BUT_W/2))
#define OPT_OK_Y (OPTION_Y+368-(OPT_BUT_W/2))
#define OPT_CAN_X (OPTION_X+350)
#define OPT_CAN_Y (OPT_OK_Y)
#define SLIDER_TRK_X (OPTION_X+264)
#define SLIDER_TRK_W 132
#define SLIDER_TRK_H 27
#define SLIDER_W 38
#define OBJ_LABEL_X (SLIDER_TRK_X-5)
#define OBJ_LABEL_Y (OPTION_Y+60)
#define SUBTITLE_X (OPTION_X+465)
#define SUBTITLE_Y (OBJ_LABEL_Y)
#define STEREO_X (SLIDER_TRK_X-5)
#define STEREO_Y (OPTION_Y+253)
#define MUSIC_TRK_Y (OPTION_Y+121)
#define SPEECH_TRK_Y (OPTION_Y+168)
#define FX_TRK_Y (OPTION_Y+214)
#define GRFX_TRK_Y (OPTION_Y+301)
#define MUTE_W 40
#define MUTE_H 32
#define MUTE_X (SUBTITLE_X+OPT_BUT_W/2-MUTE_W/2)
#define GRFX_ICON_X (OPTION_X+450)
#define GRFX_ICON_Y (OPTION_Y+270)
//--------------------------------------------
uint8 *panel_surface;
_spriteInfo panel_sprite;
_spriteInfo slab_sprite[8];
uint8 *slab_surface[8];
_spriteInfo chr_sprite;
#define SIZE_OF_CHAR_SET (256-32) // our fonts start on SPACE character (32)
uint8 *chr_surface[SIZE_OF_CHAR_SET];
uint8 *red_chr_surface[SIZE_OF_CHAR_SET];
_spriteInfo can_button_sprite[2];
uint8 *can_button_surface[2];
uint32 can_button_state=0;
uint32 touching_can_button=0;
_spriteInfo button_sprite[2];
uint8 *button_surface[2];
uint32 restore_button_state=0;
uint32 touching_restore_button=0;
_spriteInfo up_button_sprite[2];
uint8 *up_button_surface[2];
uint32 up_button_state=0;
uint32 touching_up_button=0;
_spriteInfo down_button_sprite[2];
uint8 *down_button_surface[2];
uint32 down_button_state=0;
uint32 touching_down_button=0;
_spriteInfo zup_button_sprite[2];
uint8 *zup_button_surface[2];
uint32 zup_button_state=0;
uint32 touching_zup_button=0;
_spriteInfo zdown_button_sprite[2];
uint8 *zdown_button_surface[2];
uint32 zdown_button_state=0;
uint32 touching_zdown_button=0;
_spriteInfo grfx_icon_sprite[4];
uint8 *grfx_icon_surface[4];
uint8 *charSet;
uint8 *red_charSet;
_frameHeader *head;
uint32 base_slot=0;
uint8 subtitles; // text selected
uint8 speechSelected;
uint8 stereoReversed = 0;
uint8 current_graphics_level;
//-----------------------------------------------------------------------------------------------------------------------
uint32 Restore_control(void) //Tony20Mar97
{
//well, this is nice and hard wired - not the way to do it really
// returns 0 for no restore
// 1 for restored ok
int breakOut=0;
uint32 j;
char key_press=0;
uint8 description[SAVE_DESCRIPTION_LEN];
uint8 buf[8][SAVE_DESCRIPTION_LEN];
uint8 chr;
int char_no;
_mouseEvent *me;
uint8 restore_text[MAX_STRING_LEN];
uint8 cancel_text[MAX_STRING_LEN];
uint8 *text;
uint32 slab_text_x;
uint32 slab_text_y;
uint32 slot=1000; //nothing selected
uint32 clicked_slot;
uint32 cur_slot_states[9];
int scroll_rate=0;
//static uint32 base_slot=0;
int first=0;
uint32 rv; // return value for RestoreGame
uint32 res; //result from primer game cycle
int names_built=0; //0 redo, else dont
//do some driver stuff
// for (j=0;j<1000;j++)
// ResetRenderEngine();
//buttons unpressed
restore_button_state=0;
can_button_state=0;
Build_surfaces();
Build_chr_surfaces();
//fetch the 'restore' text
text = FetchTextLine( res_man.Res_open(149618690/SIZE), 149618690&0xffff ); // open text file & get the line
strcpy((char*)&restore_text[0], (char*)text+2);
//fetch the 'cancel' text
text = FetchTextLine( res_man.Res_open(149618689/SIZE), 149618689&0xffff ); // open text file & get the line
strcpy((char*)&cancel_text[0], (char*)text+2);
//blimey, life's never easy is it?
//control loop
while (1)
{
//--------------------------------------------------
// Service windows
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q during the smacker
{
Close_game(); //close engine systems down
CloseAppWindow();
exit(0); //quit the game
}
while (!gotTheFocus)
{ names_built=0;
slot=1000;
if (ServiceWindows() == RDERR_APPCLOSED)
break;
}
//--------------------------------------------------
EraseBackBuffer();
//print panel
if (DrawSurface(&panel_sprite, panel_surface)==RDERR_SURFACELOST)
Renew_surfaces();
//print words on panel
Engine_string(REST_BUT_X+32, REST_BUT_Y, controls_font_id, chr_surface, restore_text);
Engine_string(CAN_BUT_X+32, REST_BUT_Y, controls_font_id, chr_surface, cancel_text);
slab_text_y=76;
// print slabs
for (j=0;j<8;j++)
{
if (slot==base_slot+j) //red
{ slab_sprite[((base_slot+j)&3)+4].y=SLAB_Y+(j*SLAB_Y_SPACING);
DrawSurface(&slab_sprite[((base_slot+j)&3)+4], slab_surface[((base_slot+j)&3)+4] );
}
else
{ slab_sprite[((base_slot+j)&3)].y=SLAB_Y+(j*SLAB_Y_SPACING);
DrawSurface(&slab_sprite[((base_slot+j)&3)], slab_surface[((base_slot+j)&3)] );
}
// print save name on slab if a game is saved in this slot
if (!names_built)
{ if (GetSaveDescription(base_slot+j, description) == SR_OK) //if there is a savegame at this slot
{
cur_slot_states[j]=1; //slot used
if (!description[0])
Con_fatal_error("NULL file name passed from GetSaveDescription!");
// print the name on the slab
sprintf((char*)buf[j], "%d. %s", base_slot+j, description );
}
else
{
sprintf((char*)buf[j], "%d.", base_slot+j); //simply print the number
cur_slot_states[j]=0; //slot not used
}
}
char_no=0;
slab_text_x=SLAB_X+16;
do
{
chr = buf[j][char_no];
chr-=32; //got true chr$
chr_sprite.x=slab_text_x;
chr_sprite.scale=0;
chr_sprite.type= RDSPR_NOCOMPRESSION+RDSPR_TRANS;
chr_sprite.blend= 0;
if (slot==base_slot+j)
{
head = (_frameHeader *)FetchFrameHeader(red_charSet, chr);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
chr_sprite.y=slab_text_y+2;
DrawSurface(&chr_sprite, red_chr_surface[chr]); //print
}
else
{
head = (_frameHeader *)FetchFrameHeader(charSet, chr);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
chr_sprite.y=slab_text_y;
DrawSurface(&chr_sprite, chr_surface[chr]); //print
}
slab_text_x+=head->width-CHARACTER_OVERLAP;
char_no++;
}
while(buf[j][char_no]);
slab_text_y+=SLAB_Y_SPACING;
}
names_built=1; //dont GetSaveDescription each cycle
//print buttons
//print restore button
DrawSurface(&button_sprite[restore_button_state], button_surface[restore_button_state] );
//print cancel button
DrawSurface(&can_button_sprite[can_button_state], can_button_surface[can_button_state] );
//print up button
DrawSurface(&up_button_sprite[up_button_state], up_button_surface[up_button_state] );
//print down button
DrawSurface(&down_button_sprite[down_button_state], down_button_surface[down_button_state] );
//print zup button
DrawSurface(&zup_button_sprite[zup_button_state], zup_button_surface[zup_button_state] );
//print zdown button
DrawSurface(&zdown_button_sprite[zdown_button_state], zdown_button_surface[zdown_button_state] );
ProcessMenu();
if (!first)
{
first++;
SetFullPalette(CONTROL_PANEL_PALETTE); // see Build_display.cpp (James17jun97)
}
//mouse over buttons?
//restore
if ((mousex>REST_BUT_X)&&(mousex<REST_BUT_X+24)&&((mousey+40)>REST_BUT_Y)&&((mousey+40)<REST_BUT_Y+24))
touching_restore_button=1; //mouse over button
else //not over so release even if pressed previously
{ restore_button_state=0;
touching_restore_button=0;
}
//cancel
if ((mousex>CAN_BUT_X)&&(mousex<CAN_BUT_X+24)&&((mousey+40)>CAN_BUT_Y)&&((mousey+40)<CAN_BUT_Y+24))
touching_can_button=1; //mouse over button
else //not over so release even if pressed previously
{ can_button_state=0;
touching_can_button=0;
}
//up
if ((mousex>UP_BUT_X)&&(mousex<UP_BUT_X+17)&&((mousey+40)>UP_BUT_Y)&&((mousey+40)<UP_BUT_Y+17))
touching_up_button=1; //mouse over button
else //not over so release even if pressed previously
{ up_button_state=0;
touching_up_button=0;
}
//down
if ((mousex>DOWN_BUT_X)&&(mousex<DOWN_BUT_X+17)&&((mousey+40)>DOWN_BUT_Y)&&((mousey+40)<DOWN_BUT_Y+17))
touching_down_button=1; //mouse over button
else //not over so release even if pressed previously
{ down_button_state=0;
touching_down_button=0;
}
//up
if ((mousex>UP_BUT_X)&&(mousex<UP_BUT_X+17)&&((mousey+40)>ZUP_BUT_Y)&&((mousey+40)<ZUP_BUT_Y+17))
touching_zup_button=1; //mouse over button
else //not over so release even if pressed previously
{ zup_button_state=0;
touching_zup_button=0;
}
//down
if ((mousex>DOWN_BUT_X)&&(mousex<DOWN_BUT_X+17)&&((mousey+40)>ZDOWN_BUT_Y)&&((mousey+40)<ZDOWN_BUT_Y+17))
touching_zdown_button=1; //mouse over button
else //not over so release even if pressed previously
{ zdown_button_state=0;
touching_zdown_button=0;
}
//check mouse clicked on a slab
me = MouseEvent(); //get mouse event
if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed
{
if ((mousex>SLAB_X)&&(mousex<SLAB_X+384)&&((mousey+40)>SLAB_Y)&&((mousey+40)<SLAB_Y+SLAB_Y_SPACING*8))
{
clicked_slot=((mousey+40)-SLAB_Y)/SLAB_Y_SPACING;
//Zdebug("clicked slab %d", slot);
if (cur_slot_states[clicked_slot]) //a selectable slot
{
if (slot!= clicked_slot+base_slot) //can select if not selected now
slot=clicked_slot+base_slot; //now selected
else slot=1000; //else deselect
}
}
// clicking on the restore button
if (touching_restore_button)
restore_button_state=1; //button now down
// clicking on the cancel button
if (touching_can_button)
can_button_state=1; //button now down
// clicking on the up button
if (touching_up_button)
{ up_button_state=1; //button now down
scroll_rate=0;
}
// clicking on the down button
if (touching_down_button)
{ down_button_state=1; //button now down
scroll_rate=0;
}
// clicking on the zup button
if (touching_zup_button)
{ zup_button_state=1; //button now down
scroll_rate=0;
}
// clicking on the zdown button
if (touching_zdown_button)
{ zdown_button_state=1; //button now down
scroll_rate=0;
}
}
//check for releasing the mouse button over a button
if ((key_press==13)||((me!=NULL)&&(me->buttons&RD_LEFTBUTTONUP))) //there's a mouse event to be processed
{
if ((key_press==13)||((touching_restore_button)&&(restore_button_state)))
{
restore_button_state=0;
if (slot!=1000) //restore the game!
{
breakOut=1;
rv = RestoreGame(slot);
if (rv == SR_OK)
{
// DEAD=0; //in case we were dead - well we're not anymore!
// prime system with a game cycle
Reset_render_lists(); // reset the graphic 'buildit' list before a new logic list (see FN_register_frame)
Reset_mouse_list(); // reset the mouse hot-spot list (see FN_register_mouse & FN_register_frame)
res = LLogic.Process_session();
if (res)
Con_fatal_error("restart 1st cycle failed??");
// Control_error("restored OK :)");
Kill_surfaces();
Kill_chr_surfaces();
return(1);
}
else
{
// Save & Restore error codes
// ERROR CODE VALUE MEANING REASON
// ========== ===== ======= ======
// SR_OK 0x00000000 // ok No worries
// SR_ERR_FILEOPEN 0x00000001 // can't open file Could create file for saving, or couldn't find file for loading
// SR_ERR_INCOMPATIBLE 0x00000002 // (RestoreGame only) incompatible savegame data Savegame file is obsolete. (Won't happen after development stops)
// SR_ERR_READFAIL 0x00000003 // (RestoreGame only) failed on reading savegame file Something screwed up during the fread()
// SR_ERR_WRITEFAIL 0x00000004 // (SaveGame only) failed on writing savegame file Something screwed up during the fwrite() - could be hard-drive full..?
// WE NEED A MESSAGE BOX TO INDICATE FAILED SAVE - DON'T HALT THE GAME!
if (rv == SR_ERR_FILEOPEN)
Control_error((char*)(FetchTextLine( res_man.Res_open(213516670/SIZE), 213516670&0xffff)+2));
// Restore failed - could not open file
else if (rv == SR_ERR_INCOMPATIBLE)
Control_error((char*)(FetchTextLine( res_man.Res_open(213516671/SIZE), 213516671&0xffff)+2));
// Restore failed - incompatible savegame data
else // SR_ERR_READFAIL
Control_error((char*)(FetchTextLine( res_man.Res_open(213516673/SIZE), 213516673&0xffff)+2));
// Restore failed
}
}
}
else if ((touching_can_button)&&(can_button_state)) //quit the screen
breakOut=1;
else if (touching_up_button)
up_button_state=0;
else if (touching_down_button)
down_button_state=0;
else if (touching_zup_button)
zup_button_state=0;
else if (touching_zdown_button)
zdown_button_state=0;
}
//scrolling downward
if ( ((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(down_button_state)&&(base_slot<92))
{ base_slot++;
names_built=0;
}
//scrolling upward
if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(up_button_state)&&(base_slot))
{ base_slot--;
names_built=0;
}
//scrolling zdownward
if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(zdown_button_state)&&(base_slot<92))
{ base_slot+=8;
if (base_slot>92)
base_slot=92;
names_built=0;
}
//scrolling zupward
if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(zup_button_state)&&(base_slot))
{ base_slot-=8;
if (base_slot>92)
base_slot=0;
names_built=0;
}
//update scroll stuff
scroll_rate++;
//-----
key_press=0;
if (KeyWaiting())
{
ReadKey(&key_press); //kill the key we just pressed
if (key_press==27) //ESC
break;
}
if (breakOut)
{
break; //quit this stuff - ap will eventually close in the mainloop
}
} //while
Kill_surfaces();
Kill_chr_surfaces();
return(0);
}
//-----------------------------------------------------------------------------------------------------------------------
void Create_surface_image(_spriteInfo *sprite, uint8 **surface, uint32 res, uint32 x, uint32 y, uint32 pc) //TonyMarch97
{
uint8 *file, *colTablePtr=NULL;
_animHeader *anim_head;
_frameHeader *frame_head;
_cdtEntry *cdt_entry;
//_spriteInfo spriteInfo;
uint32 spriteType=RDSPR_TRANS;
file = res_man.Res_open(res); // open anim resource file & point to base
anim_head = FetchAnimHeader( file );
cdt_entry = FetchCdtEntry( file, pc );
frame_head = FetchFrameHeader( file, pc );
if (anim_head->blend)
spriteType += RDSPR_BLEND;
if ((cdt_entry->frameType) & FRAME_FLIPPED) //if the frame is to be flipped (only really applicable to frames using offsets)
spriteType += RDSPR_FLIP;
switch (anim_head->runTimeComp) // what compression was used?
{
case NONE:
spriteType += RDSPR_NOCOMPRESSION;
break;
case RLE256:
spriteType += RDSPR_RLE256;
break;
case RLE16:
spriteType += RDSPR_RLE16;
colTablePtr = (uint8*)(anim_head+1) + anim_head->noAnimFrames*sizeof(_cdtEntry);
// points to just after last cdt_entry, ie. start of colour table
break;
}
sprite->x = x;
sprite->y = y;
sprite->w = frame_head->width;
sprite->h = frame_head->height;
sprite->scale = 0;
// spriteInfo.scaledWidth = build_unit->scaled_width;
// spriteInfo.scaledHeight = build_unit->scaled_height;
sprite->type = spriteType;
sprite->blend = anim_head->blend;
sprite->data = (uint8*)(frame_head+1); // points to just after frame header, ie. start of sprite data
// spriteInfo.colourTable = colTablePtr;
// Zdebug("w %d h %d", frame_head->width, frame_head->height);
CreateSurface(sprite, surface);
res_man.Res_close(res); //release the anim resource
}
//-----------------------------------------------------------------------------------------------------------------------
void Build_surfaces(void) //Tony27March97
{
//setup the control window
Create_surface_image(&panel_sprite, &panel_surface, WINDOW_RES, WINDOW_X, REST_Y, 0);
//setup slabs as surfaces
Create_surface_image(&slab_sprite[0], &slab_surface[0], 2006, SLAB_X, 0, 0);
Create_surface_image(&slab_sprite[1], &slab_surface[1], 2007, SLAB_X, 0, 0);
Create_surface_image(&slab_sprite[2], &slab_surface[2], 2008, SLAB_X, 0, 0);
Create_surface_image(&slab_sprite[3], &slab_surface[3], 2009, SLAB_X, 0, 0);
//now the red selected panels
Create_surface_image(&slab_sprite[4], &slab_surface[4], 2006, SLAB_X, 0, 1);
Create_surface_image(&slab_sprite[5], &slab_surface[5], 2007, SLAB_X, 0, 1);
Create_surface_image(&slab_sprite[6], &slab_surface[6], 2008, SLAB_X, 0, 1);
Create_surface_image(&slab_sprite[7], &slab_surface[7], 2009, SLAB_X, 0, 1);
//restore button
Create_surface_image(&button_sprite[0], &button_surface[0], 2002, REST_BUT_X, REST_BUT_Y, 0);
Create_surface_image(&button_sprite[1], &button_surface[1], 2002, REST_BUT_X, REST_BUT_Y, 1);
//cancel button
Create_surface_image(&can_button_sprite[0], &can_button_surface[0], 2002, CAN_BUT_X, CAN_BUT_Y, 0);
Create_surface_image(&can_button_sprite[1], &can_button_surface[1], 2002, CAN_BUT_X, CAN_BUT_Y, 1);
//up button
Create_surface_image(&up_button_sprite[0], &up_button_surface[0], 2067, UP_BUT_X, UP_BUT_Y, 0);
Create_surface_image(&up_button_sprite[1], &up_button_surface[1], 2067, UP_BUT_X, UP_BUT_Y, 1);
//down button
Create_surface_image(&down_button_sprite[0], &down_button_surface[0], 1986, DOWN_BUT_X, DOWN_BUT_Y, 0);
Create_surface_image(&down_button_sprite[1], &down_button_surface[1], 1986, DOWN_BUT_X, DOWN_BUT_Y, 1);
//zup button
Create_surface_image(&zup_button_sprite[0], &zup_button_surface[0], 1982, UP_BUT_X, ZUP_BUT_Y, 0);
Create_surface_image(&zup_button_sprite[1], &zup_button_surface[1], 1982, UP_BUT_X, ZUP_BUT_Y, 1);
//zdown button
Create_surface_image(&zdown_button_sprite[0], &zdown_button_surface[0], 1988, DOWN_BUT_X, ZDOWN_BUT_Y, 0);
Create_surface_image(&zdown_button_sprite[1], &zdown_button_surface[1], 1988, DOWN_BUT_X, ZDOWN_BUT_Y, 1);
}
//-----------------------------------------------------------------------------------------------------------------------
void Build_chr_surfaces(void) //tony2Apr97
{
int j;
//sort out the font
charSet = res_man.Res_open(controls_font_id); //open font file
red_charSet = res_man.Res_open(red_font_id); //open font file
//set up the chr$ set frame surfaces
chr_sprite.scale=0;
chr_sprite.type= RDSPR_NOCOMPRESSION+RDSPR_TRANS;
chr_sprite.blend= 0;
for (j=0; j < SIZE_OF_CHAR_SET; j++)
{ //normal
head = (_frameHeader *)FetchFrameHeader(charSet,j);
chr_sprite.data = (uint8 *)(head+1);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
CreateSurface(&chr_sprite, &chr_surface[j]);
// red
head = (_frameHeader *)FetchFrameHeader(red_charSet,j);
chr_sprite.data = (uint8 *)(head+1);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
CreateSurface(&chr_sprite, &red_chr_surface[j]);
}
res_man.Res_close(controls_font_id); //close font file
res_man.Res_close(red_font_id); //close font file
}
//-----------------------------------------------------------------------------------------------------------------------
void Kill_surfaces(void) //Tony27March97
{
//remove the surfaces
DeleteSurface(panel_surface);
DeleteSurface(slab_surface[0]);
DeleteSurface(slab_surface[1]);
DeleteSurface(slab_surface[2]);
DeleteSurface(slab_surface[3]);
DeleteSurface(slab_surface[4]);
DeleteSurface(slab_surface[5]);
DeleteSurface(slab_surface[6]);
DeleteSurface(slab_surface[7]);
DeleteSurface(button_surface[0]);
DeleteSurface(button_surface[1]);
DeleteSurface(can_button_surface[0]);
DeleteSurface(can_button_surface[1]);
DeleteSurface(up_button_surface[0]);
DeleteSurface(up_button_surface[1]);
DeleteSurface(down_button_surface[0]);
DeleteSurface(down_button_surface[1]);
DeleteSurface(zup_button_surface[0]);
DeleteSurface(zup_button_surface[1]);
DeleteSurface(zdown_button_surface[0]);
DeleteSurface(zdown_button_surface[1]);
}
//-----------------------------------------------------------------------------------------------------------------------
void Kill_chr_surfaces(void) //Tony2Apr97
{
int j;
//release chr$ set surfaces
for (j=0; j < SIZE_OF_CHAR_SET; j++)
{ //normal
DeleteSurface(chr_surface[j]);
// red
DeleteSurface(red_chr_surface[j]);
}
}
//-----------------------------------------------------------------------------------------------------------------------
void Renew_surfaces(void) //Tony27March97
{
Kill_surfaces();
Kill_chr_surfaces();
Build_surfaces();
Build_chr_surfaces();
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
void Save_control(void) //Tony1Apr97 not a joke
{
//largely the same as the restore code
int breakOut=0;
uint32 j;
char key_press;
uint8 description[SAVE_DESCRIPTION_LEN];
uint8 buf[8][SAVE_DESCRIPTION_LEN];
uint8 ed_buf[SAVE_DESCRIPTION_LEN];
int char_no;
uint8 chr;
_mouseEvent *me;
int esc_release=0;
uint32 slab_text_x;
uint32 slab_text_y;
uint32 clicked_slot=1000, edit_screen_slot=1000;
uint32 cur_slot_states[9];
int scroll_rate=0;
// static uint32 base_slot=0;
int edit_pos=0, first_chr=0, flash=0;
uint8 save_text[MAX_STRING_LEN];
uint8 cancel_text[MAX_STRING_LEN];
uint8 *text;
int first=0;
uint32 rv; // return value for SaveGame
uint32 edit_width=0;
int names_built=0;
//buttons unpressed
restore_button_state=0;
can_button_state=0;
//do some driver stuff
// ResetRenderEngine();
//sort out the font
charSet = res_man.Res_open(controls_font_id); //open font file
red_charSet = res_man.Res_open(red_font_id); //open font file
chr_sprite.scale=0;
chr_sprite.type= RDSPR_NOCOMPRESSION+RDSPR_TRANS;
chr_sprite.blend= 0;
Build_surfaces();
Build_chr_surfaces();
//fetch the 'save' text
text = FetchTextLine( res_man.Res_open(149618691/SIZE), 149618691&0xffff ); // open text file & get the line
strcpy((char*)&save_text[0], (char*)text+2);
//fetch the 'cancel' text
text = FetchTextLine( res_man.Res_open(149618689/SIZE), 149618689&0xffff ); // open text file & get the line
strcpy((char*)&cancel_text[0], (char*)text+2);
//blimey, life's never easy is it?
//control loop
while (1)
{
//--------------------------------------------------
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q during the smacker
{
Close_game(); //close engine systems down
CloseAppWindow();
exit(0); //quit the game
}
// Service windows
while (!gotTheFocus)
{ names_built=0;
edit_screen_slot=1000;
if (ServiceWindows() == RDERR_APPCLOSED)
break;
}
//--------------------------------------------------
EraseBackBuffer();
//print panel
if (DrawSurface(&panel_sprite, panel_surface)==RDERR_SURFACELOST)
Renew_surfaces();
//print words on panel
Engine_string(REST_BUT_X+32, REST_BUT_Y, controls_font_id, chr_surface, save_text);
Engine_string(CAN_BUT_X+32, REST_BUT_Y, controls_font_id, chr_surface, cancel_text);
slab_text_y=76;
// print slabs
for (j=0;j<8;j++)
{
if (edit_screen_slot!=j)
{ slab_sprite[((base_slot+j)&3)].y=SLAB_Y+(j*SLAB_Y_SPACING);
DrawSurface(&slab_sprite[((base_slot+j)&3)], slab_surface[((base_slot+j)&3)] );
// print save name on slab if a game is saved in this slot
if (!names_built)
{
if (GetSaveDescription(base_slot+j, description) == SR_OK) //if there is a savegame at this slot
{ cur_slot_states[j]=1; //slot used
if (!description[0])
Con_fatal_error("NULL file name passed from GetSaveDescription!");
// print the name on the slab
sprintf((char*)buf[j], "%d. %s", base_slot+j, description );
}
else
{ sprintf((char*)buf[j], "%d.", base_slot+j); //simply print the number
cur_slot_states[j]=0; //slot not used
}
}
char_no=0;
slab_text_x=SLAB_X+16;
do
{
chr = buf[j][char_no];
chr-=32; //got true chr$
chr_sprite.x=slab_text_x;
head = (_frameHeader *)FetchFrameHeader(charSet, chr);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
chr_sprite.y=slab_text_y;
DrawSurface(&chr_sprite, chr_surface[chr]); //print
slab_text_x+=head->width-CHARACTER_OVERLAP; // overlap characters by 3 pixels;
char_no++;
}
while(buf[j][char_no]);
}
slab_text_y+=SLAB_Y_SPACING;
}
names_built=1;
//draw the typing slab and text if we are still editing
if (edit_screen_slot!=1000) //we are typing a name in
{
flash++;
if (flash<7)
ed_buf[edit_pos]='_';
else
ed_buf[edit_pos]=' '; //by putting a space in we'll always have a chr$ in the buffer
if (flash==14)
flash=0;
// now draw the current edit line
// draw a red slab
slab_sprite[(clicked_slot&3)+4].y=SLAB_Y+(edit_screen_slot*SLAB_Y_SPACING);
DrawSurface(&slab_sprite[(clicked_slot&3)+4], slab_surface[(clicked_slot&3)+4] );
// draw the text line
char_no=0;
edit_width=0; //total pixel width of text being typed in
slab_text_x=SLAB_X+16;
// print the chr$
do
{
chr = ed_buf[char_no];
chr-=32; //got true chr$
chr_sprite.x=slab_text_x;
head = (_frameHeader *)FetchFrameHeader(red_charSet, chr);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
chr_sprite.y=SLAB_Y+(edit_screen_slot*SLAB_Y_SPACING)+5; //why 5? when its 2 on restore????????
DrawSurface(&chr_sprite, red_chr_surface[chr]); //print
slab_text_x+=head->width-CHARACTER_OVERLAP;
edit_width+=head->width-CHARACTER_OVERLAP;
char_no++;
}
while(ed_buf[char_no]);
}
//print buttons
//print restore button
DrawSurface(&button_sprite[restore_button_state], button_surface[restore_button_state] );
//print cancel button
DrawSurface(&can_button_sprite[can_button_state], can_button_surface[can_button_state] );
//print up button
DrawSurface(&up_button_sprite[up_button_state], up_button_surface[up_button_state] );
//print down button
DrawSurface(&down_button_sprite[down_button_state], down_button_surface[down_button_state] );
//print zup button
DrawSurface(&zup_button_sprite[zup_button_state], zup_button_surface[zup_button_state] );
//print zdown button
DrawSurface(&zdown_button_sprite[zdown_button_state], zdown_button_surface[zdown_button_state] );
ProcessMenu();
//mouse over buttons?
//restore
if ((mousex>REST_BUT_X)&&(mousex<REST_BUT_X+24)&&((mousey+40)>REST_BUT_Y)&&((mousey+40)<REST_BUT_Y+24))
touching_restore_button=1; //mouse over button
else //not over so release even if pressed previously
{ restore_button_state=0;
touching_restore_button=0;
}
//cancel
if ((mousex>CAN_BUT_X)&&(mousex<CAN_BUT_X+24)&&((mousey+40)>CAN_BUT_Y)&&((mousey+40)<CAN_BUT_Y+24))
touching_can_button=1; //mouse over button
else //not over so release even if pressed previously
{ can_button_state=0;
touching_can_button=0;
}
//up
if ((mousex>UP_BUT_X)&&(mousex<UP_BUT_X+17)&&((mousey+40)>UP_BUT_Y)&&((mousey+40)<UP_BUT_Y+17))
touching_up_button=1; //mouse over button
else //not over so release even if pressed previously
{ up_button_state=0;
touching_up_button=0;
}
//down
if ((mousex>DOWN_BUT_X)&&(mousex<DOWN_BUT_X+17)&&((mousey+40)>DOWN_BUT_Y)&&((mousey+40)<DOWN_BUT_Y+17))
touching_down_button=1; //mouse over button
else //not over so release even if pressed previously
{ down_button_state=0;
touching_down_button=0;
}
//up
if ((mousex>UP_BUT_X)&&(mousex<UP_BUT_X+17)&&((mousey+40)>ZUP_BUT_Y)&&((mousey+40)<ZUP_BUT_Y+17))
touching_zup_button=1; //mouse over button
else //not over so release even if pressed previously
{ zup_button_state=0;
touching_zup_button=0;
}
//down
if ((mousex>DOWN_BUT_X)&&(mousex<DOWN_BUT_X+17)&&((mousey+40)>ZDOWN_BUT_Y)&&((mousey+40)<ZDOWN_BUT_Y+17))
touching_zdown_button=1; //mouse over button
else //not over so release even if pressed previously
{ zdown_button_state=0;
touching_zdown_button=0;
}
//check mouse clicked on a slab
me = MouseEvent(); //get mouse event
if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed
{
if ((mousex>SLAB_X)&&(mousex<SLAB_X+384)&&((mousey+40)>SLAB_Y)&&((mousey+40)<SLAB_Y+SLAB_Y_SPACING*8))
{
edit_screen_slot=((mousey+40)-SLAB_Y)/SLAB_Y_SPACING;
clicked_slot=edit_screen_slot+base_slot;
Zdebug("+ %d %d", edit_screen_slot, clicked_slot);
// now edit the line
// take a copy of the string
for (j=0;j<SAVE_DESCRIPTION_LEN;j++)
ed_buf[j]=0; //zero the string
sprintf((char*)ed_buf, "%d. ", clicked_slot); //simply print the number - assume no name in panel
first_chr=strlen((char*)ed_buf);
edit_pos=first_chr;
if (GetSaveDescription(clicked_slot, description) == SR_OK) //if there is a savegame at this slot
{
sprintf((char*)ed_buf, "%d. %s", clicked_slot, description );
edit_pos=strlen((char*)ed_buf); //recalculate cursor pos to end of string
}
Zdebug("first %d [%s]", first_chr, ed_buf);
}
// clicking on the restore button
if (touching_restore_button)
restore_button_state=1; //button now down
// clicking on the cancel button
if (touching_can_button)
can_button_state=1; //button now down
// clicking on the up button
if (touching_up_button)
{ up_button_state=1; //button now down
scroll_rate=0;
}
// clicking on the down button
if (touching_down_button)
{ down_button_state=1; //button now down
scroll_rate=0;
}
// clicking on the zup button
if (touching_zup_button)
{ zup_button_state=1; //button now down
scroll_rate=0;
}
// clicking on the zdown button
if (touching_zdown_button)
{ zdown_button_state=1; //button now down
scroll_rate=0;
}
}
//check for releasing the mouse button over a button
if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONUP)) //there's a mouse event to be processed
{
if ((touching_restore_button)&&(restore_button_state))
{
restore_button_state=0;
if ((edit_screen_slot!=1000)&&(edit_pos!=first_chr)) //we are editing and have a legal file name typed in
{ //then save game - can also be saved when you press RETurn
ed_buf[edit_pos]=0; //remove cursor/[space]
rv = SaveGame(clicked_slot, (uint8*)&ed_buf[first_chr]);
if (rv == SR_OK)
{ breakOut=1; //finished
if ((edit_screen_slot>6)&(base_slot<92))
base_slot++;
}
else
{
// Save & Restore error codes
// ERROR CODE VALUE MEANING REASON
// ========== ===== ======= ======
// SR_OK 0x00000000 // ok No worries
// SR_ERR_FILEOPEN 0x00000001 // can't open file Could create file for saving, or couldn't find file for loading
// SR_ERR_INCOMPATIBLE 0x00000002 // (RestoreGame only) incompatible savegame data Savegame file is obsolete. (Won't happen after development stops)
// SR_ERR_READFAIL 0x00000003 // (RestoreGame only) failed on reading savegame file Something screwed up during the fread()
// SR_ERR_WRITEFAIL 0x00000004 // (SaveGame only) failed on writing savegame file Something screwed up during the fwrite() - could be hard-drive full..?
// WE NEED A MESSAGE BOX TO INDICATE FAILED SAVE - DON'T HALT THE GAME!
if (rv == SR_ERR_FILEOPEN)
Control_error((char*)(FetchTextLine( res_man.Res_open(213516674/SIZE), 213516674&0xffff)+2));
// Save failed - could not open file
else // SR_ERR_WRITEFAIL
Control_error((char*)(FetchTextLine( res_man.Res_open(213516676/SIZE), 213516676&0xffff)+2));
// Save failed
}
}
}
else if ((touching_can_button)&&(can_button_state)) //quit the screen
breakOut=1;
else if (touching_up_button)
up_button_state=0;
else if (touching_down_button)
down_button_state=0;
else if (touching_zup_button)
zup_button_state=0;
else if (touching_zdown_button)
zdown_button_state=0;
}
//scrolling downward
if ( ((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(down_button_state)&&(base_slot<92))
{ base_slot++;
names_built=0;
if (edit_screen_slot!=1000)
{ edit_screen_slot--;
if (base_slot>clicked_slot)
edit_screen_slot=1000;
}
}
//scrolling upward
if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(up_button_state)&&(base_slot))
{ base_slot--;
names_built=0;
if (edit_screen_slot!=1000)
{ edit_screen_slot++;
if ((base_slot+7)<clicked_slot)
edit_screen_slot=1000;
}
}
//scrolling zdownward
if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(zdown_button_state)&&(base_slot<92))
{ base_slot+=8;
names_built=0;
if (base_slot>92)
base_slot=92;
edit_screen_slot=1000; //no more editing
}
//scrolling zupward
if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(zup_button_state)&&(base_slot))
{ base_slot-=8;
names_built=0;
if (base_slot>92)
base_slot=0;
edit_screen_slot=1000; //no more editing
}
//update scroll stuff
scroll_rate++;
//-----
//deal with user input if the user is inputting
if ((edit_screen_slot!=1000)&&(KeyWaiting())) //we are typing a name in
{
ReadKey(&key_press);
if (!key_press) //escape sequences
{
}
else if (key_press==27) //ESC
{
edit_screen_slot=1000; //quit this edit
esc_release=42; //stop the ESC key auto-repeating after this and quiting the save control
}
else if (key_press==13) //RETurn
{
if (edit_pos!=first_chr)
{ //save game
ed_buf[edit_pos]=0; //remove cursor/[space]
Zdebug("%d %d %s", first_chr, edit_pos, &ed_buf[first_chr]);
rv = SaveGame(clicked_slot, (uint8*)&ed_buf[first_chr]);
if (rv == SR_OK)
{ breakOut=1; //finished
if ((edit_screen_slot>6)&(base_slot<92))
base_slot++;
}
else
{
// Save & Restore error codes
// ERROR CODE VALUE MEANING REASON
// ========== ===== ======= ======
// SR_OK 0x00000000 // ok No worries
// SR_ERR_FILEOPEN 0x00000001 // can't open file Could create file for saving, or couldn't find file for loading
// SR_ERR_INCOMPATIBLE 0x00000002 // (RestoreGame only) incompatible savegame data Savegame file is obsolete. (Won't happen after development stops)
// SR_ERR_READFAIL 0x00000003 // (RestoreGame only) failed on reading savegame file Something screwed up during the fread()
// SR_ERR_WRITEFAIL 0x00000004 // (SaveGame only) failed on writing savegame file Something screwed up during the fwrite() - could be hard-drive full..?
// WE NEED A MESSAGE BOX TO INDICATE FAILED SAVE - DON'T HALT THE GAME!
if (rv == SR_ERR_FILEOPEN)
Control_error((char*)(FetchTextLine( res_man.Res_open(213516674/SIZE), 213516674&0xffff)+2));
// Save failed - could not open file
else // SR_ERR_WRITEFAIL
Control_error((char*)(FetchTextLine( res_man.Res_open(213516676/SIZE), 213516676&0xffff)+2));
// Save failed
}
}
else edit_screen_slot=1000; //dont save an empty slot and cancel editing
}
else if (key_press==8) //delete
{
if (edit_pos!=first_chr)
{
ed_buf[edit_pos]=0; //delete cursor chr$
edit_pos--;
ed_buf[edit_pos]=0;
}
}
else if ((key_press<32)||(key_press>'z'))
Zdebug("save ignoring key - %d", key_press);
else
{
// if (edit_pos<(20)) //less one to leave room for the cursor
if ((edit_width<350)&&(edit_pos<SAVE_DESCRIPTION_LEN-2))
ed_buf[edit_pos++]=key_press;
else //end of line has been reached, so keep replacing last letter
ed_buf[edit_pos-1]=key_press; //replace
}
}
else if (KeyWaiting())
{
ReadKey(&key_press); //kill the key we just pressed
if ((key_press==27)&&(!esc_release)) //ESC
breakOut=1;
else if (key_press!=27)
esc_release=0;
}
else if (!KeyWaiting())
esc_release=0;
if (breakOut)
{
break; //quit this stuff - ap will eventually close in the mainloop
}
if (!first)
{
first++;
SetFullPalette(CONTROL_PANEL_PALETTE); // see Build_display.cpp (James17jun97)
}
} //while
Kill_surfaces();
Kill_chr_surfaces();
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
void Quit_control(void) //Tony2Apr97
{
uint32 res;
res=Generic_mini_control(149618692); //quit text
if (!res)
return; //just return to game
EraseBackBuffer();
Close_game(); //close engine systems down
CloseAppWindow();
exit(0);
}
//-----------------------------------------------------------------------------------------------------------------------
void Restart_control(void) //Tony4Apr97
{
uint32 res;
uint32 temp_demo_flag;
res=Generic_mini_control(149618693); //restart text
if (!res)
return; //just return to game
Kill_music(); // Stop music instantly! (James22aug97)
DEAD=0; //in case we were dead - well we're not anymore!
//clean up surface memory
Kill_mini_surfaces();
EraseBackBuffer();
//ProcessMenu(); //draw menu
//restart the game
//clear all memory and reset the globals
temp_demo_flag = DEMO;
res_man.Remove_all_res(); //remove all resources from memory, including player object & global variables
SetGlobalInterpreterVariables((int32*)(res_man.Res_open(1)+sizeof(_standardHeader))); //reopen global variables resource & send address to interpreter - it won't be moving
res_man.Res_close(1);
DEMO = temp_demo_flag;
FreeAllRouteMem(); // free all the route memory blocks from previous game
g_sword2->Start_game(); // call the same function that first started us up
//prime system with a game cycle
Reset_render_lists(); // reset the graphic 'buildit' list before a new logic list (see FN_register_frame)
Reset_mouse_list(); // reset the mouse hot-spot list (see FN_register_mouse & FN_register_frame)
CloseMenuImmediately();
//---------------------------------------------------------------
// FOR THE DEMO - FORCE THE SCROLLING TO BE RESET! (James29may97)
// - this is taken from FN_init_background
this_screen.scroll_flag = 2; // switch on scrolling (2 means first time on screen)
//---------------------------------------------------------------
res = LLogic.Process_session();
if (res)
Con_fatal_error("restart 1st cycle failed??");
this_screen.new_palette=99; // (JEL08oct97) so palette not restored immediately after control panel - we want to fade up instead!
}
//-----------------------------------------------------------------------------------------------------------------------
uint32 Generic_mini_control(uint32 text_id) //Tony2Apr97
{
// returns 1 for OK pressed
// returns 0 for CANCEL pressed
int breakOut=0;
char c;
uint8 quit_text[MAX_STRING_LEN];
uint8 ok_text[MAX_STRING_LEN];
uint8 cancel_text[MAX_STRING_LEN];
uint8 *text;
_mouseEvent *me;
int first=0;
int text_len;
#define OK_BUT_X (QUIT_X+40)
#define OK_BUT_Y (QUIT_Y+110)
#define CAN_BU_Y (QUIT_Y+172)
//do some driver stuff
// ResetRenderEngine();
//fetch the 'quit' text
text = FetchTextLine( res_man.Res_open(text_id/SIZE), text_id&0xffff ); //quit or restart
strcpy((char*)&quit_text[0], (char*)text+2);
text_len = Pixel_text_length(&quit_text[0], controls_font_id);
//fetch the 'ok' text
text = FetchTextLine( res_man.Res_open(149618688/SIZE), 149618688&0xffff ); //ok
strcpy((char*)&ok_text[0], (char*)text+2);
//fetch the 'cancel' text
text = FetchTextLine( res_man.Res_open(149618689/SIZE), 149618689&0xffff ); //cancel
strcpy((char*)&cancel_text[0], (char*)text+2);
//blimey, life's never easy is it?
//buttons unpressed
restore_button_state=0;
can_button_state=0;
//build surfaces
Build_mini_surfaces();
//control loop
while (1)
{
//--------------------------------------------------
// Service windows
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q
{
Close_game(); //close engine systems down
CloseAppWindow();
exit(0); //quit the game
}
while (!gotTheFocus)
if (ServiceWindows() == RDERR_APPCLOSED)
break;
//--------------------------------------------------
EraseBackBuffer();
//print panel
if (DrawSurface(&panel_sprite, panel_surface)==RDERR_SURFACELOST)
{
Kill_mini_surfaces();
Build_mini_surfaces();
}
//print words on panel quit_x+81
Engine_string(310-(text_len/2), QUIT_Y+30, controls_font_id, chr_surface, quit_text); // quit
Engine_string(QUIT_X+67, QUIT_Y+110, controls_font_id, chr_surface, ok_text); // ok
Engine_string(QUIT_X+67, QUIT_Y+172, controls_font_id, chr_surface, cancel_text); // cancel
//print buttons
//print ok button
DrawSurface(&button_sprite[restore_button_state], button_surface[restore_button_state] );
//print cancel button
DrawSurface(&can_button_sprite[can_button_state], can_button_surface[can_button_state] );
//keep menu up too
ProcessMenu();
//user can ESC quit
if (KeyWaiting())
{
ReadKey(&c); //kill the key we just pressed
if (c==27) //ESC
break;
}
//mouse over ok button?
if ((mousex>OK_BUT_X)&&(mousex<OK_BUT_X+24)&&((mousey+40)>OK_BUT_Y)&&((mousey+40)<OK_BUT_Y+24))
touching_restore_button=1; //mouse over button
else //not over so release even if pressed previously
{ restore_button_state=0;
touching_restore_button=0;
}
//mouse over cancel button?
if ((mousex>OK_BUT_X)&&(mousex<OK_BUT_X+24)&&((mousey+40)>CAN_BU_Y)&&((mousey+40)<CAN_BU_Y+24))
touching_can_button=1; //mouse over button
else //not over so release even if pressed previously
{ can_button_state=0;
touching_can_button=0;
}
//pressing on a button
me = MouseEvent(); //get mouse event
if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed
{
if (touching_restore_button)
restore_button_state=1;
if (touching_can_button)
can_button_state=1;
}
else if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONUP))
{
if ((touching_restore_button)&&(restore_button_state)) //quit the game
{
return(1);
}
if ((touching_can_button)&&(can_button_state))
{ can_button_state=0;
breakOut=1;
}
}
if (breakOut)
break;
if (!first)
{
first++;
SetFullPalette(CONTROL_PANEL_PALETTE); // see Build_display.cpp (James17jun97)
}
}
Kill_mini_surfaces();
return(0);
}
//-----------------------------------------------------------------------------------------------------------------------
void Build_mini_surfaces(void) //tony3Apr97
{
Create_surface_image(&panel_sprite, &panel_surface, 1996, QUIT_X, QUIT_Y, 0);
//ok button
Create_surface_image(&button_sprite[0], &button_surface[0], 2002, OK_BUT_X, OK_BUT_Y, 0);
Create_surface_image(&button_sprite[1], &button_surface[1], 2002, OK_BUT_X, OK_BUT_Y, 1);
//cancel button
Create_surface_image(&can_button_sprite[0], &can_button_surface[0], 2002, OK_BUT_X, CAN_BU_Y, 0);
Create_surface_image(&can_button_sprite[1], &can_button_surface[1], 2002, OK_BUT_X, CAN_BU_Y, 1);
Build_chr_surfaces();
}
//-----------------------------------------------------------------------------------------------------------------------
void Kill_mini_surfaces(void) //tony3Apr97
{
DeleteSurface(panel_surface);
//ok button
DeleteSurface(button_surface[0]);
DeleteSurface(button_surface[1]);
//cancel button
DeleteSurface(can_button_surface[0]);
DeleteSurface(can_button_surface[1]);
Kill_chr_surfaces();
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
void Engine_string(uint32 x, uint32 y, uint32 res, uint8 **surface_list, uint8 *buf) //tony2Apr97
{
//takes fonts as sprites and prints transparently to screen
//requires the chr$ surfaces have been setup
int char_no=0;
int chr;
uint8 *chars;
chars = res_man.Res_open(res); //open font file
chr_sprite.scale=0;
chr_sprite.type= RDSPR_NOCOMPRESSION+RDSPR_TRANS;
chr_sprite.blend= 0;
chr_sprite.x=x;
chr_sprite.y=y;
do
{
chr = buf[char_no];
chr-=32; //got true chr$
head = (_frameHeader *)FetchFrameHeader(chars, chr);
chr_sprite.w=head->width;
chr_sprite.h=head->height;
DrawSurface(&chr_sprite, surface_list[chr]); //print
chr_sprite.x+=head->width-CHARACTER_OVERLAP;
char_no++;
}
while(buf[char_no]);
res_man.Res_close(res); //close font file
}
//-----------------------------------------------------------------------------------------------------------------------
uint32 Pixel_text_length(uint8 *buf, uint32 res) //tony4Apr97
{
int char_no=0;
int chr;
uint8 *chars;
uint32 width=0;
chars = res_man.Res_open(res); //open font file
do
{
chr = buf[char_no];
chr-=32; //got true chr$
head = (_frameHeader *)FetchFrameHeader(chars, chr);
width+=head->width-CHARACTER_OVERLAP;
char_no++;
}
while(buf[char_no]);
res_man.Res_close(res); //close font file
return(width);
}
//-----------------------------------------------------------------------------------------------------------------------
void Control_error(char* text) //Tony13May97
{
//print a message on screen, wait for key, return
_mouseEvent *me;
char c;
DisplayMsg( (uint8*)text, 0 ); // 2nd param is duration
while (1)
{
//--------------------------------------------------
// Service windows
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q during the smacker
{
Close_game(); //close engine systems down
CloseAppWindow();
exit(0); //quit the game
}
while (!gotTheFocus)
if (ServiceWindows() == RDERR_APPCLOSED)
break;
//--------------------------------------------------
if (KeyWaiting())
{
ReadKey(&c); //kill the key we just pressed
if (c==27) //ESC
break;
}
me = MouseEvent(); //get mouse event
if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed
break;
}
RemoveMsg(); // Removes the message.
}
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
int32 ReadOptionSettings(void) //pete10Jun97
{
// settings file is 9 bytes long, bytes 1 to 3 = music, speech and fx volumes
// bytes 4 to 6 = music, speech and fx mute states, byte 7 = grfx level
// byte 8 = subtitle state and byte 9 = object label state.
uint8 buff[10];
char filename[256];
SaveFile *fp;
SaveFileManager *mgr = g_system->get_savefile_manager();
sprintf(filename, "%s-settings.dat", g_sword2->_game_name);
if (!(fp = mgr->open_savefile(filename, g_sword2->getSavePath(), false)))
return (1);
if (fp->read(buff, 10) != 10)
{
delete fp;
delete mgr;
return (2);
}
delete fp;
delete mgr;
g_sword2->_sound->SetMusicVolume(buff[0]);
g_sword2->_sound->SetSpeechVolume(buff[1]);
g_sword2->_sound->SetFxVolume(buff[2]);
g_sword2->_sound->MuteMusic(buff[3]);
g_sword2->_sound->MuteSpeech(buff[4]);
g_sword2->_sound->MuteFx(buff[5]);
UpdateGraphicsLevel(buff[6]); // (James13jun97)
speechSelected = !buff[4];
subtitles = buff[7];
pointerTextSelected = buff[8];
if (buff[9] != stereoReversed)
g_sword2->_sound->ReverseStereo();
stereoReversed = buff[9];
return (0);
}
//-----------------------------------------------------------------------------------------------------------------------
int32 WriteOptionSettings(void) //pete10Jun97
{
uint8 buff[10];
char filename[256];
SaveFile *fp;
SaveFileManager *mgr = g_system->get_savefile_manager();
sprintf(filename, "%s-settings.dat", g_sword2->_game_name);
buff[0] = g_sword2->_sound->GetMusicVolume();
buff[1] = g_sword2->_sound->GetSpeechVolume();
buff[2] = g_sword2->_sound->GetFxVolume();
buff[3] = g_sword2->_sound->IsMusicMute();
buff[4] = g_sword2->_sound->IsSpeechMute();
buff[5] = g_sword2->_sound->IsFxMute();
buff[6] = GetRenderType();
buff[7] = subtitles;
buff[8] = pointerTextSelected;
buff[9] = stereoReversed;
if (!(fp = mgr->open_savefile(filename, g_sword2->getSavePath(), true)))
return (1);
if (fp->write(buff, 10) != 10)
{
delete fp;
delete mgr;
return (2);
}
delete fp;
delete mgr;
return (0);
}
//-----------------------------------------------------------------------------------------------------------------------
void Build_option_surfaces(void) //pete6Jun97
{
Create_surface_image(&panel_sprite, &panel_surface, 3405, 0, OPTION_Y, 0);
// object label button
Create_surface_image(&up_button_sprite[0], &up_button_surface[0], 3687, OBJ_LABEL_X,OBJ_LABEL_Y, 0);
Create_surface_image(&up_button_sprite[1], &up_button_surface[1], 3687, OBJ_LABEL_X,OBJ_LABEL_Y, 1);
//subtitle button
Create_surface_image(&down_button_sprite[0], &down_button_surface[0], 3687, SUBTITLE_X, SUBTITLE_Y, 0);
Create_surface_image(&down_button_sprite[1], &down_button_surface[1], 3687, SUBTITLE_X, SUBTITLE_Y, 1);
//ok button
Create_surface_image(&button_sprite[0], &button_surface[0], 901, OPT_OK_X, OPT_OK_Y, 0);
Create_surface_image(&button_sprite[1], &button_surface[1], 901, OPT_OK_X, OPT_OK_Y, 1);
//cancel button
Create_surface_image(&can_button_sprite[0], &can_button_surface[0], 901, OPT_CAN_X, OPT_CAN_Y, 0);
Create_surface_image(&can_button_sprite[1], &can_button_surface[1], 901, OPT_CAN_X, OPT_CAN_Y, 1);
//sliders
Create_surface_image(&slab_sprite[0], &slab_surface[0], 3406, SLIDER_TRK_X,MUSIC_TRK_Y,0); // music slider
Create_surface_image(&slab_sprite[1], &slab_surface[1], 3406, SLIDER_TRK_X,SPEECH_TRK_Y,0); // speech slider
Create_surface_image(&slab_sprite[2], &slab_surface[2], 3406, SLIDER_TRK_X,FX_TRK_Y,0); // fx slider
Create_surface_image(&slab_sprite[3], &slab_surface[3], 3406, SLIDER_TRK_X,GRFX_TRK_Y,0); // graphics slider
//mute buttons
Create_surface_image(&zup_button_sprite[0], &zup_button_surface[0], 3315, MUTE_X, MUSIC_TRK_Y-4, 0); // music mute
Create_surface_image(&zup_button_sprite[1], &zup_button_surface[1], 3315, MUTE_X, MUSIC_TRK_Y-4, 1);
Create_surface_image(&zdown_button_sprite[0], &zdown_button_surface[0],3315, MUTE_X, SPEECH_TRK_Y-3, 0);// speech mute
Create_surface_image(&zdown_button_sprite[1], &zdown_button_surface[1],3315, MUTE_X, SPEECH_TRK_Y-3, 1);
Create_surface_image(&slab_sprite[4], &slab_surface[4], 3315, MUTE_X,FX_TRK_Y-4,0); // fx mute
Create_surface_image(&slab_sprite[5], &slab_surface[5], 3315, MUTE_X,FX_TRK_Y-4,1);
//graphics level icon
Create_surface_image(&grfx_icon_sprite[0], &grfx_icon_surface[0], 256, GRFX_ICON_X, GRFX_ICON_Y, 0); // lowest grapihics level icon
Create_surface_image(&grfx_icon_sprite[1], &grfx_icon_surface[1], 256, GRFX_ICON_X, GRFX_ICON_Y, 1); // medium low grapihics level icon
Create_surface_image(&grfx_icon_sprite[2], &grfx_icon_surface[2], 256, GRFX_ICON_X, GRFX_ICON_Y, 2); // mewdium high grapihics level icon
Create_surface_image(&grfx_icon_sprite[3], &grfx_icon_surface[3], 256, GRFX_ICON_X, GRFX_ICON_Y, 3); // highest grapihics level icon
//reverse stereo button
Create_surface_image(&slab_sprite[6], &slab_surface[6], 3687, STEREO_X,STEREO_Y,0);
Create_surface_image(&slab_sprite[7], &slab_surface[7], 3687, STEREO_X,STEREO_Y,1);
Build_chr_surfaces();
}
//-----------------------------------------------------------------------------------------------------------------------
void Kill_option_surfaces(void) //pete6Jun97
{
DeleteSurface(panel_surface);
//object label button
DeleteSurface(up_button_surface[0]);
DeleteSurface(up_button_surface[1]);
//subtitle button
DeleteSurface(down_button_surface[0]);
DeleteSurface(down_button_surface[1]);
//ok button
DeleteSurface(button_surface[0]);
DeleteSurface(button_surface[1]);
//cancel button
DeleteSurface(can_button_surface[0]);
DeleteSurface(can_button_surface[1]);
//sliders
DeleteSurface(slab_surface[0]);
DeleteSurface(slab_surface[1]);
DeleteSurface(slab_surface[2]);
DeleteSurface(slab_surface[3]);
//mute buttons
DeleteSurface(zup_button_surface[0]);
DeleteSurface(zup_button_surface[1]);
DeleteSurface(zdown_button_surface[0]);
DeleteSurface(zdown_button_surface[1]);
DeleteSurface(slab_surface[4]);
DeleteSurface(slab_surface[5]);
//graphics level icon
DeleteSurface(grfx_icon_surface[0]);
DeleteSurface(grfx_icon_surface[1]);
DeleteSurface(grfx_icon_surface[2]);
DeleteSurface(grfx_icon_surface[3]);
//reverse stereo icon
DeleteSurface(slab_surface[6]);
DeleteSurface(slab_surface[7]);
Kill_chr_surfaces();
}
//-----------------------------------------------------------------------------------------------------------------------
int Mouse_touching_button(int32 x, int32 y, int32 w, int32 h) //pete9Jun97
{
if ((mousex>x)&&(mousex<x+w)&&((mousey+40)>y)&&((mousey+40)<y+h))
return (1);
else
return (0);
}
//-----------------------------------------------------------------------------------------------------------------------
void Option_control(void) //Pete6Jun97
{
#define WORD_BUTTON_GAP 10
// some things left by the last tennant
char c;
_mouseEvent *me;
int first = 0;
// text strings and lengths
uint8 title_text[MAX_STRING_LEN];
uint8 subtitle_text[MAX_STRING_LEN];
uint8 object_text[MAX_STRING_LEN];
uint8 ok_text[MAX_STRING_LEN];
uint8 cancel_text[MAX_STRING_LEN];
uint8 music_text[MAX_STRING_LEN];
uint8 speech_text[MAX_STRING_LEN];
uint8 fx_text[MAX_STRING_LEN];
uint8 graphics_text[MAX_STRING_LEN];
uint8 stereo_text[MAX_STRING_LEN];
uint8 *text;
int title_len, subtitle_len, ok_len, cancel_len, left_align, test_len;
// slider values
uint8 musicVolume = g_sword2->_sound->GetMusicVolume();
uint8 speechVolume = g_sword2->_sound->GetSpeechVolume();
uint8 fxVolume = g_sword2->_sound->GetFxVolume();
uint8 grfxLevel = GetRenderType();
// safe slider values for restoring on cancel
//uint8 safe_musicVolume = musicVolume;
//uint8 safe_speechVolume = speechVolume;
//uint8 safe_fxVolume = fxVolume;
// button state variables
uint8 dreverse_stereo_state = 0, dmusic_mute_state = 0, dspeech_mute_state = 0, dfx_mute_state = 0, dobject_state = 0, dsubtitle_state = 0;
uint8 touching_reverse_stereo = 0, touching_music_mute = 0, touching_fx_mute = 0, touching_speech_mute = 0, touching_object = 0, touching_subtitle = 0;
uint8 lb_down = 0;
// Slider targets
uint8 music_target = musicVolume;
uint8 fx_target = fxVolume;
uint8 speech_target = speechVolume;
uint8 grfx_target = grfxLevel;
// Slider movement types (click in track or drag button)
uint8 music_tracking = 0, fx_tracking = 0, speech_tracking = 0, grfx_tracking = 0;
//do some driver stuff
// ResetRenderEngine();
// FETCH THE TEXT
//fetch the 'options' text
text = FetchTextLine( res_man.Res_open(149618698/SIZE), 149618698&0xffff ); //options (title)
strcpy((char*)title_text, (char*)text+2);
title_len = Pixel_text_length(title_text, controls_font_id);
//fetch the 'subtitles' text
text = FetchTextLine( res_man.Res_open(149618699/SIZE), 149618699&0xffff ); //subtitles
strcpy((char*)subtitle_text, (char*)text+2);
subtitle_len = Pixel_text_length(subtitle_text, controls_font_id) + WORD_BUTTON_GAP;
//fetch the 'object labels' text
text = FetchTextLine( res_man.Res_open(149618700/SIZE), 149618700&0xffff ); //object
strcpy((char*)object_text, (char*)text+2);
left_align = Pixel_text_length(object_text, controls_font_id) + WORD_BUTTON_GAP;
//fetch the 'ok' text
text = FetchTextLine( res_man.Res_open(149618688/SIZE), 149618688&0xffff ); //ok
strcpy((char*)ok_text, (char*)text+2);
ok_len = Pixel_text_length(ok_text, controls_font_id) + WORD_BUTTON_GAP;
//fetch the 'cancel' text
text = FetchTextLine( res_man.Res_open(149618689/SIZE), 149618689&0xffff ); //cancel
strcpy((char*)cancel_text, (char*)text+2);
cancel_len = Pixel_text_length(cancel_text, controls_font_id) + WORD_BUTTON_GAP;
//fetch the 'music volume' text
text = FetchTextLine( res_man.Res_open(149618702/SIZE), 149618702&0xffff ); //music volume
strcpy((char*)music_text, (char*)text+2);
test_len = Pixel_text_length(music_text, controls_font_id) + WORD_BUTTON_GAP;
if (test_len>left_align)
left_align = test_len;
//fetch the 'speech volume' text
text = FetchTextLine( res_man.Res_open(149618703/SIZE), 149618703&0xffff ); //speech volume
strcpy((char*)speech_text, (char*)text+2);
test_len = Pixel_text_length(speech_text, controls_font_id) + WORD_BUTTON_GAP;
if (test_len>left_align)
left_align = test_len;
//fetch the 'fx volume' text
text = FetchTextLine( res_man.Res_open(149618704/SIZE), 149618704&0xffff ); //fx volume
strcpy((char*)fx_text, (char*)text+2);
test_len = Pixel_text_length(fx_text, controls_font_id) + WORD_BUTTON_GAP;
if (test_len>left_align)
left_align = test_len;
//fetch the 'grapihics quality' text
text = FetchTextLine( res_man.Res_open(149618705/SIZE), 149618705&0xffff ); //graphics quality
strcpy((char*)graphics_text, (char*)text+2);
test_len = Pixel_text_length(graphics_text, controls_font_id) + WORD_BUTTON_GAP;
if (test_len>left_align)
left_align = test_len;
//fetch the 'grapihics quality' text
text = FetchTextLine( res_man.Res_open(149618709/SIZE), 149618709&0xffff ); //graphics quality
strcpy((char*)stereo_text, (char*)text+2);
test_len = Pixel_text_length(stereo_text, controls_font_id) + WORD_BUTTON_GAP;
if (test_len>left_align)
left_align = test_len;
//blimey, life's never easy is it?
//not once you've got out of bed !
//set the button states
restore_button_state = 0;
can_button_state = 0;
touching_object = 0;
touching_subtitle = 0;
uint8 object_state = pointerTextSelected;
uint8 subtitle_state = subtitles;
uint8 stereo_state = stereoReversed;
uint8 music_mute_state = g_sword2->_sound->IsMusicMute();
uint8 speech_mute_state = g_sword2->_sound->IsSpeechMute();
uint8 fx_mute_state = g_sword2->_sound->IsFxMute();
//build the button surfaces surfaces
Build_option_surfaces();
//position the sliders
slab_sprite[0].x = SLIDER_TRK_X + (SLIDER_TRK_W * musicVolume) / 16;
slab_sprite[1].x = SLIDER_TRK_X + (SLIDER_TRK_W * speechVolume) / 14;
slab_sprite[2].x = SLIDER_TRK_X + (SLIDER_TRK_W * fxVolume) / 14;
slab_sprite[3].x = SLIDER_TRK_X + (SLIDER_TRK_W * grfxLevel) / 3;
//control loop
while (1)
{
// Update any moving sliders
// music
if (slab_sprite[0].x<SLIDER_TRK_X + (SLIDER_TRK_W * music_target) / 16)
{
if ((SLIDER_TRK_X + (SLIDER_TRK_W * music_target) / 16)-slab_sprite[0].x<2)
slab_sprite[0].x++;
else
slab_sprite[0].x +=2;
musicVolume = (int)((float)((slab_sprite[0].x-SLIDER_TRK_X)*16)/(float)SLIDER_TRK_W+0.5);
}
else if (slab_sprite[0].x>SLIDER_TRK_X + (SLIDER_TRK_W * music_target) / 16)
{
if (slab_sprite[0].x-(SLIDER_TRK_X + (SLIDER_TRK_W * music_target) / 16)<2)
slab_sprite[0].x--;
else
slab_sprite[0].x -=2;
musicVolume = (int)((float)((slab_sprite[0].x-SLIDER_TRK_X)*16)/(float)SLIDER_TRK_W+0.5);
if (!musicVolume)
music_mute_state = 1;
else
music_mute_state = 0;
}
// speech
if (slab_sprite[1].x<SLIDER_TRK_X + (SLIDER_TRK_W * speech_target) / 14)
{
if ((SLIDER_TRK_X + (SLIDER_TRK_W * speech_target) / 14)-slab_sprite[1].x<2)
slab_sprite[1].x++;
else
slab_sprite[1].x +=2;
speechVolume = (int)((float)((slab_sprite[1].x-SLIDER_TRK_X)*14)/(float)SLIDER_TRK_W+0.5);
}
else if (slab_sprite[1].x>SLIDER_TRK_X + (SLIDER_TRK_W * speech_target) / 14)
{
if (slab_sprite[1].x-(SLIDER_TRK_X + (SLIDER_TRK_W * speech_target) / 14)<2)
slab_sprite[1].x--;
else
slab_sprite[1].x -=2;
speechVolume = (int)((float)((slab_sprite[1].x-SLIDER_TRK_X)*14)/(float)SLIDER_TRK_W+0.5);
if (!speechVolume)
speech_mute_state = 1;
else
speech_mute_state = 0;
}
// fx
if (slab_sprite[2].x<SLIDER_TRK_X + (SLIDER_TRK_W * fx_target) / 14)
{
if ((SLIDER_TRK_X + (SLIDER_TRK_W * fx_target) / 14)-slab_sprite[2].x<2)
slab_sprite[2].x++;
else
slab_sprite[2].x +=2;
fxVolume = (int)((float)((slab_sprite[2].x-SLIDER_TRK_X)*14)/(float)SLIDER_TRK_W+0.5);
}
else if (slab_sprite[2].x>SLIDER_TRK_X + (SLIDER_TRK_W * fx_target) / 14)
{
if (slab_sprite[2].x-(SLIDER_TRK_X + (SLIDER_TRK_W * fx_target) / 14)<2)
slab_sprite[2].x--;
else
slab_sprite[2].x -=2;
fxVolume = (int)((float)((slab_sprite[2].x-SLIDER_TRK_X)*14)/(float)SLIDER_TRK_W+0.5);
if (!fxVolume)
fx_mute_state = 1;
else
fx_mute_state = 0;
}
// grfx
if (slab_sprite[3].x<SLIDER_TRK_X + (SLIDER_TRK_W * grfx_target) / 3)
{
if ((SLIDER_TRK_X + (SLIDER_TRK_W * grfx_target) / 3)-slab_sprite[3].x<2)
slab_sprite[3].x++;
else
slab_sprite[3].x +=2;
grfxLevel = (int)((float)((slab_sprite[3].x-SLIDER_TRK_X)*3)/(float)SLIDER_TRK_W+0.5);
}
else if (slab_sprite[3].x>SLIDER_TRK_X + (SLIDER_TRK_W * grfx_target) / 3)
{
if (slab_sprite[3].x-(SLIDER_TRK_X + (SLIDER_TRK_W * grfx_target) / 3)<2)
slab_sprite[3].x--;
else
slab_sprite[3].x -=2;
grfxLevel = (int)((float)((slab_sprite[3].x-SLIDER_TRK_X)*3)/(float)SLIDER_TRK_W+0.5);
}
if (music_tracking) // music tracking
{
slab_sprite[0].x = mousex - SLIDER_W/2;
if (slab_sprite[0].x < SLIDER_TRK_X)
slab_sprite[0].x = SLIDER_TRK_X;
else if (slab_sprite[0].x > SLIDER_TRK_X+SLIDER_TRK_W)
slab_sprite[0].x = SLIDER_TRK_X+SLIDER_TRK_W;
music_target = musicVolume = (int)((float)((slab_sprite[0].x-SLIDER_TRK_X)*16)/(float)SLIDER_TRK_W+0.5);
if (!musicVolume)
music_mute_state = 1;
else
music_mute_state = 0;
}
else if (speech_tracking) // speech tracking
{
slab_sprite[1].x = mousex - SLIDER_W/2;
if (slab_sprite[1].x < SLIDER_TRK_X)
slab_sprite[1].x = SLIDER_TRK_X;
else if (slab_sprite[1].x > SLIDER_TRK_X+SLIDER_TRK_W)
slab_sprite[1].x = SLIDER_TRK_X+SLIDER_TRK_W;
speech_target = speechVolume = (int)((float)((slab_sprite[1].x-SLIDER_TRK_X)*14)/(float)SLIDER_TRK_W+0.5);
if (!speechVolume)
speech_mute_state = 1;
else
speech_mute_state = 0;
}
else if (fx_tracking) // fx tracking
{
slab_sprite[2].x = mousex - SLIDER_W/2;
if (slab_sprite[2].x < SLIDER_TRK_X)
slab_sprite[2].x = SLIDER_TRK_X;
else if (slab_sprite[2].x > SLIDER_TRK_X+SLIDER_TRK_W)
slab_sprite[2].x = SLIDER_TRK_X+SLIDER_TRK_W;
fx_target = fxVolume = (int)((float)((slab_sprite[2].x-SLIDER_TRK_X)*14)/(float)SLIDER_TRK_W+0.5);
if (!fxVolume)
fx_mute_state = 1;
else
fx_mute_state = 0;
}
else if (grfx_tracking) // grfx tracking
{
slab_sprite[3].x = mousex - SLIDER_W/2;
if (slab_sprite[3].x < SLIDER_TRK_X)
slab_sprite[3].x = SLIDER_TRK_X;
else if (slab_sprite[3].x > SLIDER_TRK_X+SLIDER_TRK_W)
slab_sprite[3].x = SLIDER_TRK_X+SLIDER_TRK_W;
grfx_target = grfxLevel = (int)((float)((slab_sprite[3].x-SLIDER_TRK_X)*3)/(float)SLIDER_TRK_W+0.5);
}
if (!music_mute_state)
g_sword2->_sound->SetMusicVolume(musicVolume);
else
g_sword2->_sound->SetMusicVolume(0);
if (!fx_mute_state)
g_sword2->_sound->SetFxVolume(fxVolume);
else
g_sword2->_sound->SetFxVolume(0);
if (!speech_mute_state)
g_sword2->_sound->SetSpeechVolume(speechVolume);
else
g_sword2->_sound->SetSpeechVolume(0);
//--------------------------------------------------
// Service windows
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q during the smacker
{
Close_game(); //close engine systems down
CloseAppWindow();
exit(0); //quit the game
}
while (!gotTheFocus)
if (ServiceWindows() == RDERR_APPCLOSED)
break;
//--------------------------------------------------
EraseBackBuffer();
//print panel
while (DrawSurface(&panel_sprite, panel_surface)==RDERR_SURFACELOST)
{
Kill_option_surfaces();
Build_option_surfaces();
};
//print words on panel option panel
Engine_string(OPTION_W/2-(title_len/2)+OPTION_X,OPTION_Y+15, controls_font_id, chr_surface, title_text); //options
Engine_string(SUBTITLE_X-subtitle_len, SUBTITLE_Y+3, controls_font_id, chr_surface, subtitle_text); //subtitles
Engine_string(SLIDER_TRK_X-left_align, OBJ_LABEL_Y+3, controls_font_id, chr_surface, object_text); //object labels
Engine_string(OPT_OK_X-ok_len, OPT_OK_Y, controls_font_id, chr_surface, ok_text); //ok
Engine_string(OPT_CAN_X-cancel_len, OPT_CAN_Y, controls_font_id, chr_surface, cancel_text); //cancel
Engine_string(SLIDER_TRK_X-left_align, MUSIC_TRK_Y, controls_font_id, chr_surface, music_text); //music volume
Engine_string(SLIDER_TRK_X-left_align, SPEECH_TRK_Y, controls_font_id, chr_surface, speech_text); //speech volume
Engine_string(SLIDER_TRK_X-left_align, FX_TRK_Y, controls_font_id, chr_surface, fx_text); //fx volume
Engine_string(SLIDER_TRK_X-left_align, GRFX_TRK_Y, controls_font_id, chr_surface, graphics_text); //graphics quality
Engine_string(SLIDER_TRK_X-left_align, STEREO_Y+3, controls_font_id, chr_surface, stereo_text); //reverse stereo
//print buttons
DrawSurface(&down_button_sprite[subtitle_state], down_button_surface[subtitle_state] ); //print subtitles button
DrawSurface(&up_button_sprite[object_state], up_button_surface[object_state] ); //print object labels button
DrawSurface(&button_sprite[restore_button_state], button_surface[restore_button_state] ); //print ok button
DrawSurface(&can_button_sprite[can_button_state], can_button_surface[can_button_state] ); //print cancel button
DrawSurface(&slab_sprite[0], slab_surface[0]); //print sliders
DrawSurface(&slab_sprite[1], slab_surface[1]);
DrawSurface(&slab_sprite[2], slab_surface[2]);
DrawSurface(&slab_sprite[3], slab_surface[3]);
DrawSurface(&zup_button_sprite[music_mute_state], zup_button_surface[music_mute_state] ); //print mute buttons
DrawSurface(&zdown_button_sprite[speech_mute_state], zdown_button_surface[speech_mute_state] );
DrawSurface(&slab_sprite[fx_mute_state+4], slab_surface[fx_mute_state+4] );
DrawSurface(&grfx_icon_sprite[grfxLevel], grfx_icon_surface[grfxLevel] ); //print the graphics level icon
DrawSurface(&slab_sprite[6+stereo_state], slab_surface[6+stereo_state]); // print reverse stereo button
//keep menu up too
ProcessMenu();
//user can ESC quit
if (KeyWaiting())
{
ReadKey(&c); //kill the key we just pressed
if (c==27) //ESC
{
ReadOptionSettings(); // Reset options to previous settings.
break;
}
}
// check what if anything the mouse is touching
//mouse over ok button?
if (Mouse_touching_button(OPT_OK_X,OPT_OK_Y,OPT_BUT_W,OPT_BUT_H))
touching_restore_button=1; //mouse over button
else //not over so release even if pressed previously
{ restore_button_state=0;
touching_restore_button=0;
}
//mouse over cancel button?
if (Mouse_touching_button(OPT_CAN_X,OPT_CAN_Y,OPT_BUT_W,OPT_BUT_H))
touching_can_button=1; //mouse over button
else //not over so release even if pressed previously
{ can_button_state=0;
touching_can_button=0;
}
//mouse over object label button?
if (Mouse_touching_button(OBJ_LABEL_X,OBJ_LABEL_Y,OPT_BUT_W,OPT_BUT_H))
{
if (!lb_down)
touching_object=1; //mouse over button
}
else //not over so release even if pressed previously
{
if (touching_object && lb_down && !dobject_state)
object_state=!object_state;
touching_object=0;
}
//mouse over subtitles button?
if (Mouse_touching_button(SUBTITLE_X,SUBTITLE_Y,OPT_BUT_W,OPT_BUT_H))
{
if (!lb_down)
touching_subtitle=1; //mouse over button
}
else //not over so release even if pressed previously
{
if (touching_subtitle && lb_down && !dsubtitle_state)
subtitle_state=!subtitle_state;
touching_subtitle=0;
}
//mouse over reverse stereo button?
if (Mouse_touching_button(STEREO_X,STEREO_Y,OPT_BUT_W,OPT_BUT_H))
{
if (!lb_down)
touching_reverse_stereo=1; //mouse over button
}
else //not over so release even if pressed previously
{
if (touching_reverse_stereo && lb_down && !dreverse_stereo_state)
stereo_state=!stereo_state;
touching_reverse_stereo=0;
}
//mouse over music mute button?
if (Mouse_touching_button(MUTE_X,MUSIC_TRK_Y-4,MUTE_W,MUTE_H))
{
if (!lb_down)
touching_music_mute=1; //mouse over button
}
else //not over so release even if pressed previously
{
if (touching_music_mute && lb_down && !dmusic_mute_state)
music_mute_state=!music_mute_state;
touching_music_mute=0;
}
//mouse over fx mute button?
if (Mouse_touching_button(MUTE_X,FX_TRK_Y-4,MUTE_W,MUTE_H))
{
if (!lb_down)
touching_fx_mute=1; //mouse over button
}
else //not over so release even if pressed previously
{
if (touching_fx_mute && lb_down && !dfx_mute_state)
fx_mute_state=!fx_mute_state;
touching_fx_mute=0;
}
//mouse over speech mute button?
if (Mouse_touching_button(MUTE_X,SPEECH_TRK_Y-4,MUTE_W,MUTE_H))
{
if (!lb_down)
touching_speech_mute=1; //mouse over button
}
else //not over so release even if pressed previously
{
if (touching_speech_mute && lb_down && !dspeech_mute_state)
speech_mute_state=!speech_mute_state;
touching_speech_mute=0;
}
//pressing on a button
me = MouseEvent(); //get mouse event
if (me!=NULL)
{
if (me->buttons&RD_LEFTBUTTONUP)
{
lb_down = 0;
if (touching_restore_button && restore_button_state) // ok to settings
{
UpdateGraphicsLevel(grfxLevel); // (James13jun97)
g_sword2->_sound->MuteMusic(music_mute_state); // Ensure all the levels are recorded correctly (Pete21Aug97)
g_sword2->_sound->MuteSpeech(speech_mute_state);
g_sword2->_sound->MuteFx(fx_mute_state);
g_sword2->_sound->SetMusicVolume(music_target);
g_sword2->_sound->SetSpeechVolume(speech_target);
g_sword2->_sound->SetFxVolume(fx_target);
subtitles = subtitle_state; // Save object label and subtitle settings
pointerTextSelected = object_state;
speechSelected = !speech_mute_state;
if (stereo_state != stereoReversed)
g_sword2->_sound->ReverseStereo();
stereoReversed = stereo_state;
WriteOptionSettings();
break;
}
if (touching_can_button && can_button_state) // cancel, so restore old settings
{
ReadOptionSettings();
break;
}
if (touching_object && dobject_state)
dobject_state = object_state=0; // if the button was in now let it out
if (touching_subtitle && dsubtitle_state)
subtitle_state = dsubtitle_state = 0; // if the button was in now let it out
if (touching_reverse_stereo && dreverse_stereo_state)
dreverse_stereo_state = stereo_state = 0; // if the button was in now let it out
if (touching_music_mute && dmusic_mute_state) {
music_mute_state = dmusic_mute_state = 0; // if the button was in now let it out
g_sword2->_sound->MuteMusic(0);
}
if (touching_fx_mute && dfx_mute_state) {
fx_mute_state = dfx_mute_state = 0; // if the button was in now let it out
g_sword2->_sound->MuteFx(0);
}
if (touching_speech_mute && dspeech_mute_state) {
speech_mute_state = dspeech_mute_state = 0; // if the button was in now let it out
g_sword2->_sound->MuteSpeech(0);
}
// Stop tracking any sliders
music_tracking = fx_tracking = speech_tracking = grfx_tracking = 0;
}
else if (me->buttons&RD_LEFTBUTTONDOWN) //there's a mouse event to be processed
{
lb_down = 1;
if (touching_restore_button)
restore_button_state=1;
if (touching_can_button)
can_button_state=1;
if (touching_object)
{
if (object_state) // push in the button if it's out
dobject_state = 1;
else
object_state=!object_state;
}
if (touching_subtitle)
{
if (subtitle_state)
dsubtitle_state = 1;
else
subtitle_state=!subtitle_state;
}
if (touching_reverse_stereo)
{
if (stereo_state) // push in the button if it's out
dreverse_stereo_state = 1;
else
stereo_state = !stereo_state;
}
if (touching_music_mute)
{
if (music_mute_state)
dmusic_mute_state = 1;
else
{
music_mute_state = 1;
g_sword2->_sound->MuteMusic(1);
}
}
if (touching_fx_mute)
{
if (fx_mute_state)
dfx_mute_state = 1;
else
{
fx_mute_state=1;
g_sword2->_sound->MuteFx(1);
}
}
if (touching_speech_mute)
{
if (speech_mute_state)
dspeech_mute_state = 1;
else
{
speech_mute_state=1;
g_sword2->_sound->MuteSpeech(1);
}
}
if (Mouse_touching_button(SLIDER_TRK_X,MUSIC_TRK_Y,SLIDER_TRK_W+SLIDER_W,SLIDER_TRK_H))
{
if (music_mute_state)
{
music_mute_state = 0;
g_sword2->_sound->MuteMusic(0);
}
if (mousex>(slab_sprite[0].x+SLIDER_W))
{
if (music_target<musicVolume)
music_target = musicVolume;
music_target++;
if (music_target>15)
music_target = 15;
}
else if (mousex<slab_sprite[0].x)
{
if (music_target>musicVolume)
music_target = musicVolume;
music_target--;
if (music_target>15)
music_target = 0;
} else
music_tracking = 1;
}
if (Mouse_touching_button(SLIDER_TRK_X,SPEECH_TRK_Y,SLIDER_TRK_W+SLIDER_W,SLIDER_TRK_H))
{
if (speech_mute_state)
{
speech_mute_state = 0;
g_sword2->_sound->MuteSpeech(0);
}
if (mousex>(slab_sprite[1].x+SLIDER_W))
{
if (speech_target<speechVolume)
speech_target = speechVolume;
speech_target++;
if (speech_target>14)
speech_target = 14;
}
else if (mousex<slab_sprite[1].x)
{
if (speech_target>speechVolume)
speech_target = speechVolume;
speech_target--;
if (speech_target>14)
speech_target = 0;
} else
speech_tracking = 1;
}
if (Mouse_touching_button(SLIDER_TRK_X,FX_TRK_Y,SLIDER_TRK_W+SLIDER_W,SLIDER_TRK_H))
{
if (fx_mute_state)
{
fx_mute_state = 0;
g_sword2->_sound->MuteFx(0);
}
if (mousex>(slab_sprite[2].x+SLIDER_W))
{
if (fx_target<fxVolume)
fx_target = fxVolume;
fx_target++;
if (fx_target>14)
fx_target = 14;
}
else if (mousex<slab_sprite[2].x)
{
if (fx_target>fxVolume)
fx_target = fxVolume;
fx_target--;
if (fx_target>14)
fx_target = 0;
}
else
fx_tracking = 1;
fx_mute_state = 0;
}
if (Mouse_touching_button(SLIDER_TRK_X,GRFX_TRK_Y,SLIDER_TRK_W+SLIDER_W,SLIDER_TRK_H))
{
if (mousex>(slab_sprite[3].x+SLIDER_W))
{
if (grfx_target<grfxLevel)
grfx_target = grfxLevel;
grfx_target++;
if (grfx_target>3)
grfx_target = 3;
}
else if (mousex<slab_sprite[3].x)
{
if (grfx_target>grfxLevel)
grfx_target = grfxLevel;
grfx_target--;
if (grfx_target>3)
grfx_target = 0;
}
else
grfx_tracking = 1;
}
}
}
if (!first)
{
first++;
SetFullPalette(CONTROL_PANEL_PALETTE); // see Build_display.cpp (James17jun97)
}
}
Kill_option_surfaces();
return; //just return to game
}
void UpdateGraphicsLevel(uint8 newLevel) { // (James13jun97)
switch (newLevel) {
case 0: // Lowest setting: no graphics fx
ClearTransFx();
ClearShadowFx();
ClearBltFx();
break;
case 1: // Medium-low setting: transparency-blending
SetTransFx();
ClearShadowFx();
ClearBltFx();
break;
case 2: // Medium-high setting: transparency-blending + shading
SetTransFx();
SetShadowFx();
ClearBltFx();
break;
case 3: // Highest setting: transparency-blending + shading + edge-blending + improved stretching
SetTransFx();
SetShadowFx();
SetBltFx();
break;
}
// update our global variable - which needs to be checked when dimming
// the palette in PauseGame() in sword2.cpp (since palette-matching
// cannot be done with dimmed palette so we turn down one notch while
// dimmed, if at top level)
current_graphics_level = newLevel;
}