/* 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 #include #include #include //#include "src\driver96.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, uint32 *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, uint32 *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) //-------------------------------------------- uint32 panel_surface; _spriteInfo panel_sprite; _spriteInfo slab_sprite[8]; uint32 slab_surface[8]; _spriteInfo chr_sprite; #define SIZE_OF_CHAR_SET (256-32) // our fonts start on SPACE character (32) uint32 chr_surface[SIZE_OF_CHAR_SET]; uint32 red_chr_surface[SIZE_OF_CHAR_SET]; _spriteInfo can_button_sprite[2]; uint32 can_button_surface[2]; uint32 can_button_state=0; uint32 touching_can_button=0; _spriteInfo button_sprite[2]; uint32 button_surface[2]; uint32 restore_button_state=0; uint32 touching_restore_button=0; _spriteInfo up_button_sprite[2]; uint32 up_button_surface[2]; uint32 up_button_state=0; uint32 touching_up_button=0; _spriteInfo down_button_sprite[2]; uint32 down_button_surface[2]; uint32 down_button_state=0; uint32 touching_down_button=0; _spriteInfo zup_button_sprite[2]; uint32 zup_button_surface[2]; uint32 zup_button_state=0; uint32 touching_zup_button=0; _spriteInfo zdown_button_sprite[2]; uint32 zdown_button_surface[2]; uint32 zdown_button_state=0; uint32 touching_zdown_button=0; _spriteInfo grfx_icon_sprite[4]; uint32 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 uint8 *colTablePtr=NULL; int breakOut=0; uint32 j; uint8 black[4]={0,0,0,0}; 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 RestoreDisplay(); 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) } FlipScreens(); //mouse over buttons? //restore if ((mousex>REST_BUT_X)&&(mousexREST_BUT_Y)&&((mousey+40)CAN_BUT_X)&&(mousexCAN_BUT_Y)&&((mousey+40)UP_BUT_X)&&(mousexUP_BUT_Y)&&((mousey+40)DOWN_BUT_X)&&(mousexDOWN_BUT_Y)&&((mousey+40)UP_BUT_X)&&(mousexZUP_BUT_Y)&&((mousey+40)DOWN_BUT_X)&&(mousexZDOWN_BUT_Y)&&((mousey+40)buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed { if ((mousex>SLAB_X)&&(mousexSLAB_Y)&&((mousey+40)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, uint32 *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 uint8 *colTablePtr=NULL; int breakOut=0; uint32 j; uint8 black[4]={0,0,0,0}; 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 slot=1000; //nothing selected uint32 clicked_slot, edit_screen_slot=1000; uint32 cur_slot_states[9]; int scroll_rate=0; // static uint32 base_slot=0; int edit_pos, first_chr, 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; 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 RestoreDisplay(); 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)&&(mousexREST_BUT_Y)&&((mousey+40)CAN_BUT_X)&&(mousexCAN_BUT_Y)&&((mousey+40)UP_BUT_X)&&(mousexUP_BUT_Y)&&((mousey+40)DOWN_BUT_X)&&(mousexDOWN_BUT_Y)&&((mousey+40)UP_BUT_X)&&(mousexZUP_BUT_Y)&&((mousey+40)DOWN_BUT_X)&&(mousexZDOWN_BUT_Y)&&((mousey+40)buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed { if ((mousex>SLAB_X)&&(mousexSLAB_Y)&&((mousey+40)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)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_posOK_BUT_X)&&(mousexOK_BUT_Y)&&((mousey+40)OK_BUT_X)&&(mousexCAN_BU_Y)&&((mousey+40)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; FlipScreens(); 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, uint32 *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 RestoreDisplay(); 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]; FILE *fp; if ((fp = fopen("Settings.dat","rb"))== NULL) return (1); if (fread(buff,1,10,fp) != 10) { fclose(fp); return (2); } fclose(fp); SetMusicVolume(buff[0]); SetSpeechVolume(buff[1]); SetFxVolume(buff[2]); MuteMusic(buff[3]); MuteSpeech(buff[4]); MuteFx(buff[5]); UpdateGraphicsLevel(GetRenderType(), buff[6]); // (James13jun97) speechSelected = !buff[4]; subtitles = buff[7]; pointerTextSelected = buff[8]; if (buff[9] != stereoReversed) ReverseStereo(); stereoReversed = buff[9]; return (0); } //----------------------------------------------------------------------------------------------------------------------- int32 WriteOptionSettings(void) //pete10Jun97 { uint8 buff[10]; FILE *fp; buff[0] = GetMusicVolume(); buff[1] = GetSpeechVolume(); buff[2] = GetFxVolume(); buff[3] = IsMusicMute(); buff[4] = IsSpeechMute(); buff[5] = IsFxMute(); buff[6] = GetRenderType(); buff[7] = subtitles; buff[8] = pointerTextSelected; buff[9] = stereoReversed; if ((fp = fopen("Settings.dat","wb"))== NULL) return (1); if (fwrite(buff,1,10,fp) != 10) { fclose(fp); return (2); } fclose(fp); 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)&&(mousexy)&&((mousey+40)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 = IsMusicMute(); uint8 speech_mute_state = IsSpeechMute(); uint8 fx_mute_state = 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].xSLIDER_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].xSLIDER_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].xSLIDER_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].xSLIDER_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) SetMusicVolume(musicVolume); else SetMusicVolume(0); if (!fx_mute_state) SetFxVolume(fxVolume); else SetFxVolume(0); if (!speech_mute_state) SetSpeechVolume(speechVolume); else SetSpeechVolume(0); //-------------------------------------------------- // Service windows if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q during the smacker { Close_game(); //close engine systems down RestoreDisplay(); CloseAppWindow(); exit(0); //quit the game } 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(safe_grfxLevel, grfxLevel); // (James13jun97) MuteMusic(music_mute_state); // Ensure all the levels are recorded correctly (Pete21Aug97) MuteSpeech(speech_mute_state); MuteFx(fx_mute_state); SetMusicVolume(music_target); SetSpeechVolume(speech_target); SetFxVolume(fx_target); subtitles = subtitle_state; // Save object label and subtitle settings pointerTextSelected = object_state; speechSelected = !speech_mute_state; if (stereo_state != stereoReversed) 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 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 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 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; MuteMusic(1); } } if (touching_fx_mute) { if (fx_mute_state) dfx_mute_state = 1; else { fx_mute_state=1; MuteFx(1); } } if (touching_speech_mute) { if (speech_mute_state) dspeech_mute_state = 1; else { speech_mute_state=1; 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; MuteMusic(0); } if (mousex>(slab_sprite[0].x+SLIDER_W)) { if (music_target15) music_target = 15; } else if (mousexmusicVolume) 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; MuteSpeech(0); } if (mousex>(slab_sprite[1].x+SLIDER_W)) { if (speech_target14) speech_target = 14; } else if (mousexspeechVolume) 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; MuteFx(0); } if (mousex>(slab_sprite[2].x+SLIDER_W)) { if (fx_target14) fx_target = 14; } else if (mousexfxVolume) 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_target3) grfx_target = 3; } else if (mousexgrfxLevel) 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) } FlipScreens(); } Kill_option_surfaces(); return; //just return to game } //----------------------------------------------------------------------------------------------------------------------- void UpdateGraphicsLevel(uint8 oldLevel, uint8 newLevel) // (James13jun97) { switch (oldLevel) // Set the graphics level { //------------------------------- case 0: // lowest setting: h/w only; no graphics fx switch(newLevel) { case 0: break; case 1: RenderSoft(); ClearBltFx(); ClearShadowFx(); CloseBackgroundLayer(); break; case 2: RenderSoft(); ClearBltFx(); CloseBackgroundLayer(); break; case 3: // same as case 2 until case 2 has edge-blending inactivated RenderSoft(); CloseBackgroundLayer(); break; } break; //------------------------------- case 1: // medium-low setting: s/w transparency-blending switch(newLevel) { case 1: break; case 0: RenderHard(); SetUpBackgroundLayers(); // InitialiseBackgroundLayer for each layer! (see layers.cpp) break; case 2: SetShadowFx(); break; case 3: // same as case 2 until case 2 has edge-blending inactivated SetBltFx(); break; } break; //------------------------------- case 2: // medium-high setting: s/w transparency-blending + shading switch(newLevel) { case 2: break; case 3: // same as case 2 until case 2 has edge-blending inactivated SetBltFx(); break; case 1: ClearShadowFx(); break; case 0: RenderHard(); SetUpBackgroundLayers(); // InitialiseBackgroundLayer for each layer! (see layers.cpp) break; } break; //------------------------------- case 3: // highest setting: s/w transparency-blending + shading + edge-blending (& improved stretching) switch(newLevel) { case 2: ClearBltFx(); break; case 3: // same as case 2 until case 2 has edge-blending inactivated break; case 1: ClearBltFx(); ClearShadowFx(); break; case 0: RenderHard(); SetUpBackgroundLayers(); // InitialiseBackgroundLayer for each layer! (see layers.cpp) break; } break; //------------------------------- } // update our global variable - which needs to be checked when dimming the palette // in PauseGame() in sword2.cpp (since palette-matching cannot be done with dimmed palette // so we turn down one notch while dimmed, if at top level) current_graphics_level = newLevel; } //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------------------