From 0b86100456736d625951734e4a9880e54a170b5a Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 8 Sep 2003 06:38:16 +0000 Subject: Complete rewrite of the in-game dialogs (quit, restart, settings, save and load). The new code is smaller, hopefully a bit easier to read and doesn't use up all the CPU time. Of course, it may some new and exciting bugs too. ;-) svn-id: r10079 --- sword2/controls.cpp | 3749 +++++++++++++++------------------------------- sword2/driver/driver96.h | 11 +- sword2/driver/sprite.cpp | 147 +- 3 files changed, 1306 insertions(+), 2601 deletions(-) (limited to 'sword2') diff --git a/sword2/controls.cpp b/sword2/controls.cpp index bff471b817..ed21ad533b 100644 --- a/sword2/controls.cpp +++ b/sword2/controls.cpp @@ -17,13 +17,7 @@ * $Header$ */ -//----------------------------------------------------------------------------------------------------------------------- -#include -#include -#include -#include - -//#include "src\driver96.h" +// FIXME: Are all of these includes really needed? #include "stdafx.h" #include "build_display.h" @@ -47,2740 +41,1495 @@ #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 MAX_STRING_LEN 64 // 20 was too low; better to be safe ;) +#define CHARACTER_OVERLAP 2 // overlap characters by 3 pixels -#define WINDOW_X 0 +uint8 subtitles; +uint8 speechSelected; +uint8 stereoReversed = 0; -#define REST_X 84 -#define REST_Y 40 +int baseSlot = 0; -#define SLAB_X (REST_X+30) -#define SLAB_Y (REST_Y+32) +uint8 current_graphics_level; -#define REST_BUT_X 130 -#define REST_BUT_Y 377 +int32 WriteOptionSettings(void); +void Control_error(char* text); + +// our fonts start on SPACE character (32) +#define SIZE_OF_CHAR_SET (256 - 32) + +enum { + kAlignLeft, + kAlignRight, + kAlignCenter +}; + +class Sword2FontRenderer { +private: + struct Glyph { + uint8 *_data; + int _width; + int _height; + } _glyph[SIZE_OF_CHAR_SET]; + int _fontId; + +public: + Sword2FontRenderer(int fontId) : _fontId(fontId) { + uint8 *font = res_man.Res_open(fontId); + _frameHeader *head; + _spriteInfo sprite; + + sprite.type = RDSPR_NOCOMPRESSION | RDSPR_TRANS; + + for (int i = 0; i < SIZE_OF_CHAR_SET; i++) { + head = (_frameHeader *) FetchFrameHeader(font, i); + sprite.data = (uint8 *) (head + 1); + sprite.w = head->width; + sprite.h = head->height; + CreateSurface(&sprite, &_glyph[i]._data); + _glyph[i]._width = head->width; + _glyph[i]._height = head->height; + } + + res_man.Res_close(fontId); + } -#define CAN_BUT_X 350 -#define CAN_BUT_Y 377 + ~Sword2FontRenderer() { + for (int i = 0; i < SIZE_OF_CHAR_SET; i++) + DeleteSurface(_glyph[i]._data); + } -#define UP_BUT_X 516 -#define UP_BUT_Y 85 + void fetchText(int textId, char *buf) { + uint8 *data = FetchTextLine(res_man.Res_open(textId / SIZE), textId & 0xffff); + int i; -#define DOWN_BUT_X 516 -#define DOWN_BUT_Y 329 + for (i = 0; data[i + 2]; i++) { + if (buf) + buf[i] = data[i + 2]; + } + + buf[i] = 0; + res_man.Res_close(textId / SIZE); + } -#define ZUP_BUT_Y 85-20 + int getTextWidth(char *text) { + int textWidth = 0; -#define ZDOWN_BUT_Y 329+21 + for (int i = 0; text[i]; i++) + textWidth += (_glyph[text[i] - 32]._width - CHARACTER_OVERLAP); + return textWidth; + } -#define SLAB_Y_SPACING 35 + int getTextWidth(int textId) { + char text[MAX_STRING_LEN]; -#define QUIT_X 203 -#define QUIT_Y 104 + fetchText(textId, text); + return getTextWidth(text); + } -#define OPTION_X 45 -#define OPTION_Y 40 -#define OPTION_W 552 + void drawText(char *text, int x, int y, int alignment = kAlignLeft); + void drawText(int textId, int x, int y, int alignment = kAlignLeft); +}; -#define OPT_BUT_W 53 -#define OPT_BUT_H 32 +void Sword2FontRenderer::drawText(char *text, int x, int y, int alignment) { + _spriteInfo sprite; + int i; -#define OPT_OK_X (OPTION_X+(OPTION_W/3)-(OPT_BUT_W/2)) -#define OPT_OK_Y (OPTION_Y+368-(OPT_BUT_W/2)) + if (alignment != kAlignLeft) { + int textWidth = getTextWidth(text); -#define OPT_CAN_X (OPTION_X+350) -#define OPT_CAN_Y (OPT_OK_Y) + switch (alignment) { + case kAlignRight: + x -= textWidth; + break; + case kAlignCenter: + x -= (textWidth / 2); + break; + } + } -#define SLIDER_TRK_X (OPTION_X+264) -#define SLIDER_TRK_W 132 -#define SLIDER_TRK_H 27 -#define SLIDER_W 38 + sprite.x = x; + sprite.y = y; -#define OBJ_LABEL_X (SLIDER_TRK_X-5) -#define OBJ_LABEL_Y (OPTION_Y+60) + for (i = 0; text[i]; i++) { + sprite.w = _glyph[text[i] - 32]._width; + sprite.h = _glyph[text[i] - 32]._height; -#define SUBTITLE_X (OPTION_X+465) -#define SUBTITLE_Y (OBJ_LABEL_Y) + DrawSurface(&sprite, _glyph[text[i] - 32]._data); -#define STEREO_X (SLIDER_TRK_X-5) -#define STEREO_Y (OPTION_Y+253) + sprite.x += (_glyph[(int) text[i] - 32]._width - CHARACTER_OVERLAP); + } +} -#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) +void Sword2FontRenderer::drawText(int textId, int x, int y, int alignment) { + char text[MAX_STRING_LEN]; -#define MUTE_W 40 -#define MUTE_H 32 -#define MUTE_X (SUBTITLE_X+OPT_BUT_W/2-MUTE_W/2) + fetchText(textId, text); + drawText(text, x, y, alignment); +} -#define GRFX_ICON_X (OPTION_X+450) -#define GRFX_ICON_Y (OPTION_Y+270) +class Sword2Dialog; -//-------------------------------------------- +typedef struct Surface { + uint8 *_surface; + bool _original; +} WidgetSurface; -uint8 *panel_surface; -_spriteInfo panel_sprite; +class Sword2Widget { +protected: + Sword2Dialog *_parent; -_spriteInfo slab_sprite[8]; -uint8 *slab_surface[8]; + _spriteInfo *_sprites; + WidgetSurface *_surfaces; + int _numStates; + int _state; -_spriteInfo chr_sprite; + ScummVM::Rect _hitRect; -#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]; +public: + Sword2Widget(Sword2Dialog *parent, int states) : + _parent(parent), _numStates(states), _state(0) { + _sprites = (_spriteInfo *) calloc(states, sizeof(_spriteInfo)); + _surfaces = (WidgetSurface *) calloc(states, sizeof(WidgetSurface)); -_spriteInfo can_button_sprite[2]; -uint8 *can_button_surface[2]; -uint32 can_button_state=0; -uint32 touching_can_button=0; + _hitRect.left = _hitRect.right = _hitRect.top = _hitRect.bottom = -1; + } -_spriteInfo button_sprite[2]; -uint8 *button_surface[2]; -uint32 restore_button_state=0; -uint32 touching_restore_button=0; + virtual ~Sword2Widget() { + for (int i = 0; i < _numStates; i++) { + if (_surfaces[i]._original) + DeleteSurface(_surfaces[i]._surface); + } + free(_sprites); + free(_surfaces); + } -_spriteInfo up_button_sprite[2]; -uint8 *up_button_surface[2]; -uint32 up_button_state=0; -uint32 touching_up_button=0; + void createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc); + void linkSurfaceImage(Sword2Widget *from, int state, int x, int y); -_spriteInfo down_button_sprite[2]; -uint8 *down_button_surface[2]; -uint32 down_button_state=0; -uint32 touching_down_button=0; + void createSurfaceImages(uint32 res, int x, int y) { + for (int i = 0; i < _numStates; i++) + createSurfaceImage(i, res, x, y, i); + } -_spriteInfo zup_button_sprite[2]; -uint8 *zup_button_surface[2]; -uint32 zup_button_state=0; -uint32 touching_zup_button=0; + void linkSurfaceImages(Sword2Widget *from, int x, int y) { + for (int i = 0; i < from->_numStates; i++) + linkSurfaceImage(from, i, x, y); + } -_spriteInfo zdown_button_sprite[2]; -uint8 *zdown_button_surface[2]; -uint32 zdown_button_state=0; -uint32 touching_zdown_button=0; + void setHitRect(int x, int y, int width, int height) { + _hitRect.left = x; + _hitRect.right = x + width; + _hitRect.top = y; + _hitRect.bottom = y + height; + } -_spriteInfo grfx_icon_sprite[4]; -uint8 *grfx_icon_surface[4]; + bool isHit(int16 x, int16 y) { + return _hitRect.left >= 0 && _hitRect.contains(x, y); + } -uint8 *charSet; -uint8 *red_charSet; + void setState(int state) { + if (state != _state) { + _state = state; + paint(); + } + } -_frameHeader *head; + int getState() { + return _state; + } -uint32 base_slot=0; + virtual void paint(ScummVM::Rect *clipRect = NULL) { + DrawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect); + } -uint8 subtitles; // text selected -uint8 speechSelected; -uint8 stereoReversed = 0; + virtual void onMouseEnter() {} + virtual void onMouseExit() {} + virtual void onMouseMove(int x, int y) {} + virtual void onMouseDown(int x, int y) {} + virtual void onMouseUp(int x, int y) {} + virtual void onKey(char key) {} + virtual void onTick() {} -uint8 current_graphics_level; + virtual void releaseMouse(int x, int y) {} +}; -//----------------------------------------------------------------------------------------------------------------------- -uint32 Restore_control(void) //Tony20Mar97 -{ -//well, this is nice and hard wired - not the way to do it really +void Sword2Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc) { + uint8 *file, *colTablePtr = NULL; + _animHeader *anim_head; + _frameHeader *frame_head; + _cdtEntry *cdt_entry; + uint32 spriteType = RDSPR_TRANS; -// returns 0 for no restore -// 1 for restored ok + // open anim resource file, point to base + file = res_man.Res_open(res); + anim_head = FetchAnimHeader(file); + cdt_entry = FetchCdtEntry(file, pc); + frame_head = FetchFrameHeader(file, pc); - int breakOut=0; - uint32 j; - char key_press=0; - uint8 description[SAVE_DESCRIPTION_LEN]; - uint8 buf[8][SAVE_DESCRIPTION_LEN]; + // If the frame is flipped. (Only really applicable to frames using + // offsets.) - uint8 chr; - int char_no; - _mouseEvent *me; + if (cdt_entry->frameType & FRAME_FLIPPED) + spriteType |= RDSPR_FLIP; - uint8 restore_text[MAX_STRING_LEN]; - uint8 cancel_text[MAX_STRING_LEN]; - uint8 *text; + // Which compression was used? + switch (anim_head->runTimeComp) { + case NONE: + spriteType |= RDSPR_NOCOMPRESSION; + break; + case RLE256: + spriteType |= RDSPR_RLE256; + break; + case RLE16: + spriteType |= RDSPR_RLE256; + // Points to just after last cdt_entry, i.e. start of + // colour table + colTablePtr = (uint8 *) (anim_head + 1) + + anim_head->noAnimFrames * sizeof(_cdtEntry); + break; + } - uint32 slab_text_x; - uint32 slab_text_y; + _sprites[state].x = x; + _sprites[state].y = y; + _sprites[state].w = frame_head->width; + _sprites[state].h = frame_head->height; + _sprites[state].scale = 0; + _sprites[state].type = spriteType; + _sprites[state].blend = anim_head->blend; + + // Points to just after frame header, ie. start of sprite data + _sprites[state].data = (uint8 *) (frame_head + 1); + + CreateSurface(&_sprites[state], &_surfaces[state]._surface); + _surfaces[state]._original = true; + + // Release the anim resource + res_man.Res_close(res); +}; + +void Sword2Widget::linkSurfaceImage(Sword2Widget *from, int state, int x, int y) { + _sprites[state].x = x; + _sprites[state].y = y; + _sprites[state].w = from->_sprites[state].w; + _sprites[state].h = from->_sprites[state].h; + _sprites[state].scale = from->_sprites[state].scale; + _sprites[state].type = from->_sprites[state].type; + _sprites[state].blend = from->_sprites[state].blend; + + _surfaces[state]._surface = from->_surfaces[state]._surface; + _surfaces[state]._original = false; +}; + +#define MAX_WIDGETS 25 + +class Sword2Dialog { +private: + int _numWidgets; + Sword2Widget *_widgets[MAX_WIDGETS]; + bool _finish; + int _result; + +public: + Sword2Dialog() : _numWidgets(0), _finish(false), _result(0) { + SetFullPalette(CONTROL_PANEL_PALETTE); + } - uint32 slot=1000; //nothing selected - uint32 clicked_slot; - uint32 cur_slot_states[9]; + virtual ~Sword2Dialog() { + for (int i = 0; i < _numWidgets; i++) + delete _widgets[i]; + } - int scroll_rate=0; - //static uint32 base_slot=0; + void registerWidget(Sword2Widget *widget) { + if (_numWidgets < MAX_WIDGETS) { + _widgets[_numWidgets++] = widget; + } + } - int first=0; + virtual void onAction(Sword2Widget *widget, int result = 0) {} - uint32 rv; // return value for RestoreGame - uint32 res; //result from primer game cycle + virtual void paint() { + EraseBackBuffer(); + for (int i = 0; i < _numWidgets; i++) + _widgets[i]->paint(); + } + virtual void setResult(int result) { + _result = result; + _finish = true; + } - int names_built=0; //0 redo, else dont + int run(); +}; +int Sword2Dialog::run() { + int i; + paint(); -//do some driver stuff -// for (j=0;j<1000;j++) -// ResetRenderEngine(); + int16 oldMouseX = -1; + int16 oldMouseY = -1; + while (!_finish) { + // So that the menu icons will reach their full size + ProcessMenu(); + ServiceWindows(); + + int16 newMouseX = mousex; + int16 newMouseY = mousey + 40; + + char key; + int32 keyboardStatus = ReadKey(&key); + _mouseEvent *me = MouseEvent(); + + if (keyboardStatus == RD_OK) { + if (key == 27) + setResult(0); + else if (key == 13) + setResult(1); + } + + for (i = 0; i < _numWidgets; i++) { + bool oldHit = _widgets[i]->isHit(oldMouseX, oldMouseY); + bool newHit = _widgets[i]->isHit(newMouseX, newMouseY); + + if (!oldHit && newHit) + _widgets[i]->onMouseEnter(); + if (oldHit && !newHit) + _widgets[i]->onMouseExit(); + if (mousex != oldMouseX || mousey != oldMouseY) + _widgets[i]->onMouseMove(newMouseX, newMouseY); + + if (me) { + switch (me->buttons) { + case RD_LEFTBUTTONDOWN: + if (newHit) + _widgets[i]->onMouseDown(newMouseX, newMouseY); + break; + + case RD_LEFTBUTTONUP: + if (newHit) + _widgets[i]->onMouseUp(newMouseX, newMouseY); + // So that slider widgets will + // know when the user releases + // the mouse button, even if + // the cursor is outside of the + // slider's hit area. + _widgets[i]->releaseMouse(newMouseX, newMouseY); + break; + } + } + if (keyboardStatus == RD_OK && key != 0) + _widgets[i]->onKey(key); -//buttons unpressed - restore_button_state=0; - can_button_state=0; + _widgets[i]->onTick(); + } + oldMouseX = newMouseX; + oldMouseY = newMouseY; + g_system->delay_msecs(20); + } + return _result; +} - Build_surfaces(); - Build_chr_surfaces(); +class Sword2Button : public Sword2Widget { +public: + Sword2Button(Sword2Dialog *parent, int x, int y, int w, int h) : + Sword2Widget(parent, 2) { + setHitRect(x, y, w, h); + } -//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? + virtual void onMouseExit() { + setState(0); + } + virtual void onMouseDown(int x, int y) { + setState(1); + } -//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 + virtual void onMouseUp(int x, int y) { + if (getState() != 0) { + setState(0); + _parent->onAction(this); } + } +}; - while (!gotTheFocus) - { names_built=0; - slot=1000; - if (ServiceWindows() == RDERR_APPCLOSED) - break; - } - //-------------------------------------------------- +class Sword2ScrollButton : public Sword2Widget { +private: + uint32 _holdCounter; - EraseBackBuffer(); +public: + Sword2ScrollButton(Sword2Dialog *parent, int x, int y, int w, int h) : + Sword2Widget(parent, 2), _holdCounter(0) { + setHitRect(x, y, w, h); + } + + virtual void onMouseExit() { + setState(0); + } + virtual void onMouseDown(int x, int y) { + setState(1); + _parent->onAction(this); + _holdCounter = 0; + } -//print panel - if (DrawSurface(&panel_sprite, panel_surface)==RDERR_SURFACELOST) - Renew_surfaces(); + virtual void onMouseUp(int x, int y) { + setState(0); + } + virtual void onTick() { + if (getState() != 0) { + _holdCounter++; + if (_holdCounter > 16 && (_holdCounter % 4) == 0) + _parent->onAction(this); + } + } +}; + +class Sword2Switch : public Sword2Widget { +private: + bool _holding, _value; + int _upState, _downState; + +public: + Sword2Switch(Sword2Dialog *parent, int x, int y, int w, int h) : + Sword2Widget(parent, 2), _holding(false), + _value(false), _upState(0), _downState(1) { + setHitRect(x, y, w, h); + } -//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); + // The sound mute switches have 0 as their "down" state and 1 as + // their "up" state, so this function is needed to get consistent + // behaviour. + void reverseStates() { + _upState = 1; + _downState = 0; + } + void setValue(bool value) { + _value = value; + if (_value) + setState(_downState); + else + setState(_upState); + } + bool getValue() { + return _value; + } - slab_text_y=76; + virtual void onMouseExit() { + if (_holding && !_value) + setState(_upState); + _holding = false; + } -// print slabs - for (j=0;j<8;j++) - { + virtual void onMouseDown(int x, int y) { + _holding = true; + setState(_downState); + } - 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] ); - } + virtual void onMouseUp(int x, int y) { + if (_holding) { + _holding = false; + _value = !_value; + if (_value) + setState(_downState); 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)] ); - } + setState(_upState); + _parent->onAction(this, getState()); + } + } +}; + +class Sword2Slider : public Sword2Widget { +private: + Sword2Widget *_background; + bool _dragging; + int _value, _targetValue; + int _maxValue; + int _dragOffset; + + int posFromValue(int value) { + return _hitRect.left + (value * (_hitRect.width() - 38)) / _maxValue; + } -// 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 + int valueFromPos(int x) { + return (int) ((double) (_maxValue * (x - _hitRect.left)) / (double) (_hitRect.width() - 38) + 0.5); + } - if (!description[0]) - Con_fatal_error("NULL file name passed from GetSaveDescription!"); +public: + Sword2Slider(Sword2Dialog *parent, Sword2Widget *background, int max, + int x, int y, int w, int h, Sword2Widget *base = NULL) : + Sword2Widget(parent, 1), _background(background), + _dragging(false), _value(0), _targetValue(0), + _maxValue(max) { + setHitRect(x, y, w, h); - // 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 - } - } + if (base) + linkSurfaceImages(base, x, y); + else + createSurfaceImages(3406, x, y); + } + virtual void paint(ScummVM::Rect *clipRect = NULL) { + // This will redraw a bit more than is strictly necessary, + // but I doubt that will make any noticeable difference. - char_no=0; + _background->paint(&_hitRect); + Sword2Widget::paint(clipRect); + } - slab_text_x=SLAB_X+16; + void setValue(int value) { + _value = value; + _targetValue = value; + _sprites[0].x = posFromValue(_value); + paint(); + } + int getValue() { + return _value; + } - do - { - chr = buf[j][char_no]; - chr-=32; //got true chr$ + virtual void onMouseMove(int x, int y) { + if (_dragging) { + int newX = x - _dragOffset; + int newValue; - chr_sprite.x=slab_text_x; + if (newX < _hitRect.left) + newX = _hitRect.left; + else if (newX + 38 > _hitRect.right) + newX = _hitRect.right - 38; + _sprites[0].x = newX; - chr_sprite.scale=0; - chr_sprite.type= RDSPR_NOCOMPRESSION+RDSPR_TRANS; - chr_sprite.blend= 0; + newValue = valueFromPos(newX); + if (newValue != _value) { + _value = newValue; + _targetValue = newValue; + _parent->onAction(this, newValue); + } - if (slot==base_slot+j) - { - head = (_frameHeader *)FetchFrameHeader(red_charSet, chr); + paint(); + } + } - chr_sprite.w=head->width; - chr_sprite.h=head->height; + virtual void onMouseDown(int x, int y) { + if (x >= _sprites[0].x && x < _sprites[0].x + 38) { + _dragging = true; + _dragOffset = x - _sprites[0].x; + } else if (x < _sprites[0].x) { + if (_targetValue > 0) + _targetValue--; + } else { + if (_targetValue < _maxValue) + _targetValue++; + } + } - chr_sprite.y=slab_text_y+2; - DrawSurface(&chr_sprite, red_chr_surface[chr]); //print - } - else - { - head = (_frameHeader *)FetchFrameHeader(charSet, chr); + virtual void releaseMouse(int x, int y) { + if (_dragging) + _dragging = false; + } - chr_sprite.w=head->width; - chr_sprite.h=head->height; + virtual void onTick() { + if (!_dragging) { + int target = posFromValue(_targetValue); + + if (target != _sprites[0].x) { + if (target < _sprites[0].x) { + _sprites[0].x -= 4; + if (_sprites[0].x < target) + _sprites[0].x = target; + } else if (target > _sprites[0].x) { + _sprites[0].x += 4; + if (_sprites[0].x > target) + _sprites[0].x = target; + } - chr_sprite.y=slab_text_y; - DrawSurface(&chr_sprite, chr_surface[chr]); //print + int newValue = valueFromPos(_sprites[0].x); + if (newValue != _value) { + _value = newValue; + _parent->onAction(this, newValue); } - slab_text_x+=head->width-CHARACTER_OVERLAP; - char_no++; + paint(); } - while(buf[j][char_no]); - - - slab_text_y+=SLAB_Y_SPACING; } + } +}; +class Sword2MiniDialog : public Sword2Dialog { +private: + int _textId; + Sword2FontRenderer *_fontRenderer; + Sword2Widget *_panel; + Sword2Button *_okButton; + Sword2Button *_cancelButton; +public: + Sword2MiniDialog(uint32 textId) : _textId(textId) { + _fontRenderer = new Sword2FontRenderer(controls_font_id); - names_built=1; //dont GetSaveDescription each cycle + _panel = new Sword2Widget(this, 1); + _panel->createSurfaceImages(1996, 203, 104); -//print buttons -//print restore button - DrawSurface(&button_sprite[restore_button_state], button_surface[restore_button_state] ); + _okButton = new Sword2Button(this, 243, 214, 24, 24); + _okButton->createSurfaceImages(2002, 243, 214); -//print cancel button - DrawSurface(&can_button_sprite[can_button_state], can_button_surface[can_button_state] ); + _cancelButton = new Sword2Button(this, 243, 276, 24, 24); + _cancelButton->linkSurfaceImages(_okButton, 243, 276); -//print up button - DrawSurface(&up_button_sprite[up_button_state], up_button_surface[up_button_state] ); + registerWidget(_panel); + registerWidget(_okButton); + registerWidget(_cancelButton); + } -//print down button - DrawSurface(&down_button_sprite[down_button_state], down_button_surface[down_button_state] ); + ~Sword2MiniDialog() { + delete _fontRenderer; + } -//print zup button - DrawSurface(&zup_button_sprite[zup_button_state], zup_button_surface[zup_button_state] ); + virtual void paint() { + Sword2Dialog::paint(); -//print zdown button - DrawSurface(&zdown_button_sprite[zdown_button_state], zdown_button_surface[zdown_button_state] ); + _fontRenderer->drawText(_textId, 310, 134, kAlignCenter); + _fontRenderer->drawText(149618688, 270, 214); // ok + _fontRenderer->drawText(149618689, 270, 276); // cancel + } + virtual void onAction(Sword2Widget *widget, int result = 0) { + if (widget == _okButton) + setResult(1); + else if (widget == _cancelButton) + setResult(0); + } +}; + +class Sword2OptionsDialog : public Sword2Dialog { +private: + Sword2FontRenderer *_fontRenderer; + Sword2Widget *_panel; + Sword2Switch *_objectLabelsSwitch; + Sword2Switch *_subtitlesSwitch; + Sword2Switch *_reverseStereoSwitch; + Sword2Switch *_musicSwitch; + Sword2Switch *_speechSwitch; + Sword2Switch *_fxSwitch; + Sword2Slider *_musicSlider; + Sword2Slider *_speechSlider; + Sword2Slider *_fxSlider; + Sword2Slider *_gfxSlider; + Sword2Widget *_gfxPreview; + Sword2Button *_okButton; + Sword2Button *_cancelButton; + +public: + Sword2OptionsDialog() { + _fontRenderer = new Sword2FontRenderer(controls_font_id); + + _panel = new Sword2Widget(this, 1); + _panel->createSurfaceImages(3405, 0, 40); + + _objectLabelsSwitch = new Sword2Switch(this, 304, 100, 53, 32); + _objectLabelsSwitch->createSurfaceImages(3687, 304, 100); + + _subtitlesSwitch = new Sword2Switch(this, 510, 100, 53, 32); + _subtitlesSwitch->linkSurfaceImages(_objectLabelsSwitch, 510, 100); + + _reverseStereoSwitch = new Sword2Switch(this, 304, 293, 53, 32); + _reverseStereoSwitch->linkSurfaceImages(_objectLabelsSwitch, 304, 293); + + _musicSwitch = new Sword2Switch(this, 516, 157, 40, 32); + _musicSwitch->createSurfaceImages(3315, 516, 157); + _musicSwitch->reverseStates(); + + _speechSwitch = new Sword2Switch(this, 516, 205, 40, 32); + _speechSwitch->linkSurfaceImages(_musicSwitch, 516, 205); + _speechSwitch->reverseStates(); + + _fxSwitch = new Sword2Switch(this, 516, 250, 40, 32); + _fxSwitch->linkSurfaceImages(_musicSwitch, 516, 250); + _fxSwitch->reverseStates(); + + _musicSlider = new Sword2Slider(this, _panel, 16, 309, 161, 170, 27); + _speechSlider = new Sword2Slider(this, _panel, 14, 309, 208, 170, 27, _musicSlider); + _fxSlider = new Sword2Slider(this, _panel, 14, 309, 254, 170, 27, _musicSlider); + _gfxSlider = new Sword2Slider(this, _panel, 3, 309, 341, 170, 27, _musicSlider); + + _gfxPreview = new Sword2Widget(this, 4); + _gfxPreview->createSurfaceImages(256, 495, 310); + + _okButton = new Sword2Button(this, 203, 382, 53, 32); + _okButton->createSurfaceImages(901, 203, 382); + + _cancelButton = new Sword2Button(this, 395, 382, 53, 32); + _cancelButton->linkSurfaceImages(_okButton, 395, 382); + + registerWidget(_panel); + registerWidget(_objectLabelsSwitch); + registerWidget(_subtitlesSwitch); + registerWidget(_reverseStereoSwitch); + registerWidget(_musicSwitch); + registerWidget(_speechSwitch); + registerWidget(_fxSwitch); + registerWidget(_musicSlider); + registerWidget(_speechSlider); + registerWidget(_fxSlider); + registerWidget(_gfxSlider); + registerWidget(_gfxPreview); + registerWidget(_okButton); + registerWidget(_cancelButton); + + ReadOptionSettings(); + + _objectLabelsSwitch->setValue(pointerTextSelected != 0); + _subtitlesSwitch->setValue(subtitles != 0); + _reverseStereoSwitch->setValue(stereoReversed != 0); + _musicSwitch->setValue(g_sword2->_sound->IsMusicMute() == 0); + _speechSwitch->setValue(g_sword2->_sound->IsSpeechMute() == 0); + _fxSwitch->setValue(g_sword2->_sound->IsFxMute() == 0); + _musicSlider->setValue(g_sword2->_sound->GetMusicVolume()); + _speechSlider->setValue(g_sword2->_sound->GetSpeechVolume()); + _fxSlider->setValue(g_sword2->_sound->GetFxVolume()); + _gfxSlider->setValue(GetRenderType()); + _gfxPreview->setState(GetRenderType()); + } - ProcessMenu(); + ~Sword2OptionsDialog() { + delete _fontRenderer; + } - if (!first) - { - first++; - SetFullPalette(CONTROL_PANEL_PALETTE); // see Build_display.cpp (James17jun97) - } + virtual void paint() { + Sword2Dialog::paint(); + int maxWidth = 0; + int width; -//mouse over buttons? -//restore - if ((mousex>REST_BUT_X)&&(mousexREST_BUT_Y)&&((mousey+40)CAN_BUT_X)&&(mousexCAN_BUT_Y)&&((mousey+40)getTextWidth(alignTextIds[i]); + if (width > maxWidth) + maxWidth = width; + } + + // Options + _fontRenderer->drawText(149618698, 321, 55, kAlignCenter); + // Subtitles + _fontRenderer->drawText(149618699, 500, 103, kAlignRight); + // Object labels + _fontRenderer->drawText(149618700, 299 - maxWidth, 103); + // Music volume + _fontRenderer->drawText(149618702, 299 - maxWidth, 161); + // Speech volume + _fontRenderer->drawText(149618703, 299 - maxWidth, 208); + // FX volume + _fontRenderer->drawText(149618704, 299 - maxWidth, 254); + // Reverse stereo + _fontRenderer->drawText(149618709, 299 - maxWidth, 296); + // Graphics quality + _fontRenderer->drawText(149618705, 299 - maxWidth, 341); + // Ok + _fontRenderer->drawText(149618688, 193, 382, kAlignRight); + // Cancel + _fontRenderer->drawText(149618689, 385, 382, kAlignRight); + } -//up - if ((mousex>UP_BUT_X)&&(mousexUP_BUT_Y)&&((mousey+40)_sound->ReverseStereo(); + stereoReversed = result; + } else if (widget == _musicSwitch) { + g_sword2->_sound->MuteMusic(result); + } else if (widget == _musicSlider) { + g_sword2->_sound->SetMusicVolume(result); + g_sword2->_sound->MuteMusic(result == 0); + _musicSwitch->setValue(result != 0); + } else if (widget == _speechSlider) { + _speechSwitch->setValue(result != 0); + } else if (widget == _fxSlider) { + _fxSwitch->setValue(result != 0); + } else if (widget == _gfxSlider) { + _gfxPreview->setState(result); + UpdateGraphicsLevel(result); + } else if (widget == _okButton) { + // Apply the changes + g_sword2->_sound->MuteMusic(_musicSwitch->getValue() == 0); + g_sword2->_sound->MuteSpeech(_speechSwitch->getValue() == 0); + g_sword2->_sound->MuteFx(_fxSwitch->getValue() == 0); + g_sword2->_sound->SetMusicVolume(_musicSlider->getValue()); + g_sword2->_sound->SetSpeechVolume(_speechSlider->getValue()); + g_sword2->_sound->SetFxVolume(_fxSlider->getValue()); + + UpdateGraphicsLevel(_gfxSlider->getValue()); + + subtitles = _subtitlesSwitch->getValue(); + pointerTextSelected = _objectLabelsSwitch->getValue(); + speechSelected = _speechSwitch->getValue(); + stereoReversed = _reverseStereoSwitch->getValue(); + + WriteOptionSettings(); + setResult(1); + } else if (widget == _cancelButton) { + // Revert the changes + ReadOptionSettings(); + setResult(0); } + } +}; + +enum { + kSaveDialog, + kLoadDialog +}; + +enum { + kSelectSlot = -1, + kDeselectSlot = -2, + kStartEditing = 0, + kCursorTick = 1 +}; + +class Sword2Slot : public Sword2Widget { +private: + int _mode; + Sword2FontRenderer *_fr; + char _text[SAVE_DESCRIPTION_LEN]; + bool _clickable; + bool _editable; + +public: + Sword2Slot(Sword2Dialog *parent, int x, int y, int w, int h) : + Sword2Widget(parent, 2), _clickable(false), + _editable(false) { + setHitRect(x, y, w, h); + _text[0] = 0; + } -//down - if ((mousex>DOWN_BUT_X)&&(mousexDOWN_BUT_Y)&&((mousey+40)UP_BUT_X)&&(mousexZUP_BUT_Y)&&((mousey+40)DOWN_BUT_X)&&(mousexZDOWN_BUT_Y)&&((mousey+40)drawText(_text, _sprites[0].x + 16, _sprites[0].y + 4 + 2 * getState()); + } -//check mouse clicked on a slab - me = MouseEvent(); //get mouse event + virtual void onMouseDown(int x, int y) { + if (_clickable) { + if (getState() == 0) { + setState(1); + _parent->onAction(this, kSelectSlot); + if (_mode == kSaveDialog) + _parent->onAction(this, kStartEditing); + } else if (_mode == kLoadDialog) { + setState(0); + _parent->onAction(this, kDeselectSlot); + } + } + } - if ((me!=NULL)&&(me->buttons&RD_LEFTBUTTONDOWN)) //there's a mouse event to be processed - { - if ((mousex>SLAB_X)&&(mousexSLAB_Y)&&((mousey+40)= ' ' && key <= 'z'))) + _parent->onAction(this, key); + } - //Zdebug("clicked slab %d", slot); + virtual void onTick() { + if (_editable) + _parent->onAction(this, kCursorTick); + } - 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 + void setY(int y) { + for (int i = 0; i < _numStates; i++) + _sprites[i].y = y; + setHitRect(_hitRect.left, y, _hitRect.width(), _hitRect.height()); + } - else slot=1000; //else deselect - } - } + int getY() { + return _sprites[0].y; + } +}; -// clicking on the restore button - if (touching_restore_button) - restore_button_state=1; //button now down +class Sword2SaveLoadDialog : public Sword2Dialog { +private: + int _mode, _selectedSlot; + char _editBuffer[SAVE_DESCRIPTION_LEN]; + int _editPos, _firstPos; + int _cursorTick; -// clicking on the cancel button - if (touching_can_button) - can_button_state=1; //button now down + Sword2FontRenderer *_fontRenderer1; + Sword2FontRenderer *_fontRenderer2; + Sword2Widget *_panel; + Sword2Slot *_slotButton[8]; + Sword2ScrollButton *_zupButton; + Sword2ScrollButton *_upButton; + Sword2ScrollButton *_downButton; + Sword2ScrollButton *_zdownButton; + Sword2Button *_okButton; + Sword2Button *_cancelButton; -// clicking on the up button - if (touching_up_button) - { up_button_state=1; //button now down - scroll_rate=0; - } +public: + Sword2SaveLoadDialog(int mode) : _mode(mode), _selectedSlot(-1) { + int i; -// 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; - } + // FIXME: The "control font" and the "red font" are currently + // always the same font, so one should be eliminated. -// clicking on the zdown button - if (touching_zdown_button) - { zdown_button_state=1; //button now down - scroll_rate=0; - } + _fontRenderer1 = new Sword2FontRenderer(controls_font_id); + _fontRenderer2 = new Sword2FontRenderer(red_font_id); + _panel = new Sword2Widget(this, 1); + _panel->createSurfaceImages(2016, 0, 40); + for (i = 0; i < 4; i++) { + _slotButton[i] = new Sword2Slot(this, 114, 0, 384, 36); + _slotButton[i]->createSurfaceImages(2006 + i, 114, 0); + _slotButton[i]->setMode(mode); + _slotButton[i + 4] = new Sword2Slot(this, 114, 0, 384, 36); + _slotButton[i + 4]->linkSurfaceImages(_slotButton[i], 114, 0); + _slotButton[i + 4]->setMode(mode); } -//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; + updateSlots(); - if (slot!=1000) //restore the game! - { - breakOut=1; + _zupButton = new Sword2ScrollButton(this, 516, 65, 17, 17); + _zupButton->createSurfaceImages(1982, 516, 65); - rv = RestoreGame(slot); + _upButton = new Sword2ScrollButton(this, 516, 85, 17, 17); + _upButton->createSurfaceImages(2067, 516, 85); - if (rv == SR_OK) - { -// DEAD=0; //in case we were dead - well we're not anymore! + _downButton = new Sword2ScrollButton(this, 516, 329, 17, 17); + _downButton->createSurfaceImages(1986, 516, 329); -// 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??"); + _zdownButton = new Sword2ScrollButton(this, 516, 350, 17, 17); + _zdownButton->createSurfaceImages(1988, 516, 350); + _okButton = new Sword2Button(this, 130, 377, 24, 24); + _okButton->createSurfaceImages(2002, 130, 377); - // Control_error("restored OK :)"); + _cancelButton = new Sword2Button(this, 350, 377, 24, 24); + _cancelButton->linkSurfaceImages(_okButton, 350, 377); - Kill_surfaces(); - Kill_chr_surfaces(); + registerWidget(_panel); - 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; + for (i = 0; i < 8; i++) + registerWidget(_slotButton[i]); - else if (touching_up_button) - up_button_state=0; + registerWidget(_zupButton); + registerWidget(_upButton); + registerWidget(_downButton); + registerWidget(_zdownButton); + registerWidget(_okButton); + registerWidget(_cancelButton); + } - else if (touching_down_button) - down_button_state=0; + ~Sword2SaveLoadDialog() { + delete _fontRenderer1; + delete _fontRenderer2; + } - else if (touching_zup_button) - zup_button_state=0; + // There aren't really a hundred different button objects of course, + // there are only eight. Re-arrange them to simulate scrolling. + + void updateSlots() { + for (int i = 0; i < 8; i++) { + Sword2Slot *slot = _slotButton[(baseSlot + i) % 8]; + Sword2FontRenderer *fr; + uint8 description[SAVE_DESCRIPTION_LEN]; + + slot->setY(72 + i * 36); + + if (baseSlot + i == _selectedSlot) { + slot->setEditable(_mode == kSaveDialog); + slot->setState(1); + fr = _fontRenderer2; + } else { + slot->setEditable(false); + slot->setState(0); + fr = _fontRenderer1; + } - else if (touching_zdown_button) - zdown_button_state=0; + if (GetSaveDescription(baseSlot + i, description) == SR_OK) { + slot->setText(fr, baseSlot + i, (char *) description); + slot->setClickable(true); + } else { + slot->setText(fr, baseSlot + i, NULL); + slot->setClickable(_mode == kSaveDialog); + } + if (slot->isEditable()) + drawEditBuffer(slot); + else + slot->paint(); } + } + virtual void onAction(Sword2Widget *widget, int result = 0) { + if (widget == _zupButton) { + if (baseSlot > 0) { + if (baseSlot >= 8) + baseSlot -= 8; + else + baseSlot = 0; + updateSlots(); + } + } else if (widget == _upButton) { + if (baseSlot > 0) { + baseSlot--; + updateSlots(); + } + } else if (widget == _downButton) { + if (baseSlot < 92) { + baseSlot++; + updateSlots(); + } + } else if (widget == _zdownButton) { + if (baseSlot < 92) { + if (baseSlot <= 84) + baseSlot += 8; + else + baseSlot = 92; + updateSlots(); + } + } else if (widget == _okButton) { + setResult(1); + } else if (widget == _cancelButton) { + setResult(0); + } else { + Sword2Slot *slot = (Sword2Slot *) widget; + + if (result >= kStartEditing) { + if (result == kStartEditing) { + if (_selectedSlot >= 10) + _firstPos = 5; + else + _firstPos = 4; + + strcpy(_editBuffer, slot->getText()); + _editPos = strlen(_editBuffer); + _cursorTick = 0; + _editBuffer[_editPos] = '_'; + _editBuffer[_editPos + 1] = 0; + slot->setEditable(true); + drawEditBuffer(slot); + } else if (result == kCursorTick) { + _cursorTick++; + if (_cursorTick == 7) { + _editBuffer[_editPos] = ' '; + drawEditBuffer(slot); + } else if (_cursorTick == 14) { + _cursorTick = 0; + _editBuffer[_editPos] = '_'; + drawEditBuffer(slot); + } + } else if (result == 8) { + if (_editPos > _firstPos) { + _editBuffer[_editPos - 1] = _editBuffer[_editPos]; + _editBuffer[_editPos--] = 0; + drawEditBuffer(slot); + } + } else { + int textWidth; + char tmp; + + tmp = _editBuffer[_editPos]; + _editBuffer[_editPos] = 0; + textWidth = _fontRenderer2->getTextWidth(_editBuffer); + _editBuffer[_editPos] = tmp; + + if (textWidth < 340 && _editPos < SAVE_DESCRIPTION_LEN - 2) { + _editBuffer[_editPos + 1] = _editBuffer[_editPos]; + _editBuffer[_editPos + 2] = 0; + _editBuffer[_editPos++] = result; + drawEditBuffer(slot); + } + } + } else { + if (result == kSelectSlot) + _selectedSlot = baseSlot + (slot->getY() - 72) / 35; + else if (result == kDeselectSlot) + _selectedSlot = -1; + + int i; + + for (i = 0; i < 8; i++) + if (widget == _slotButton[i]) + break; + + for (int j = 0; j < 8; j++) { + if (j != i) { + _slotButton[j]->setEditable(false); + _slotButton[j]->setState(0); + } + } + } + } + } + void drawEditBuffer(Sword2Slot *slot) { + if (_selectedSlot == -1) + return; -//scrolling downward - if ( ((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(down_button_state)&&(base_slot<92)) - { base_slot++; - names_built=0; - } + // This will redraw a bit more than is strictly necessary, + // but I doubt that will make any noticeable difference. -//scrolling upward - if (((scroll_rate<1)||(scroll_rate>12))&&(!(scroll_rate&3))&&(up_button_state)&&(base_slot)) - { base_slot--; - names_built=0; - } + slot->paint(); + _fontRenderer2->drawText(_editBuffer, 130, 78 + (_selectedSlot - baseSlot) * 36); + } -//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; + virtual void paint() { + Sword2Dialog::paint(); - names_built=0; + if (_mode == kLoadDialog) { + // Restore + _fontRenderer1->drawText(149618690, 165, 377); + } else { + // Save + _fontRenderer1->drawText(149618691, 165, 377); } + // Cancel + _fontRenderer1->drawText(149618689, 382, 377); + } -//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; + virtual void setResult(int result) { + // Cancel - names_built=0; + if (result == 0) { + Sword2Dialog::setResult(result); + return; } + // Save / Restore -//update scroll stuff - scroll_rate++; + if (_selectedSlot == -1) + return; + if (_mode == kSaveDialog) { + if (_editPos <= _firstPos) + return; + _editBuffer[_editPos] = 0; + uint32 rv = SaveGame(_selectedSlot, (uint8 *) &_editBuffer[_firstPos]); -//----- - key_press=0; - if (KeyWaiting()) - { - ReadKey(&key_press); //kill the key we just pressed - if (key_press==27) //ESC - break; - } + if (rv != SR_OK) { + uint32 textId; + switch (rv) { + case SR_ERR_FILEOPEN: + textId = 213516674; + break; - if (breakOut) - { - break; //quit this stuff - ap will eventually close in the mainloop - } + default: // SR_ERR_WRITEFAIL + textId = 213516676; + break; + } + Control_error((char*) (FetchTextLine(res_man.Res_open(textId / SIZE), textId & 0xffff) + 2)); + result = 0; + } + } else { + uint32 rv = RestoreGame(_selectedSlot); - } //while + if (rv != SR_OK) { + uint32 textId; + switch (rv) { + case SR_ERR_FILEOPEN: + textId = 213516670; + break; - Kill_surfaces(); - Kill_chr_surfaces(); + case SR_ERR_INCOMPATIBLE: + textId = 213516671; + break; - 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; + default: // SR_ERR_READFAIL + textId = 213516673; + break; + } + Control_error((char *) (FetchTextLine(res_man.Res_open(textId / SIZE), textId & 0xffff) + 2)); + result = 0; + } else { + // Prime system with a game cycle - file = res_man.Res_open(res); // open anim resource file & point to base + // Reset the graphic 'buildit' list before a + // new logic list (see FN_register_frame) + Reset_render_lists(); + // Reset the mouse hot-spot list (see + // FN_register_mouse and FN_register_frame) + Reset_mouse_list(); - anim_head = FetchAnimHeader( file ); - cdt_entry = FetchCdtEntry( file, pc ); - frame_head = FetchFrameHeader( file, pc ); + if (LLogic.Process_session()) + Con_fatal_error("restore 1st cycle failed??"); + } + } + Sword2Dialog::setResult(result); + } +}; +uint32 Restore_control(void) { //Tony20Mar97 + // returns 0 for no restore + // 1 for restored ok + Sword2SaveLoadDialog loadDialog(kLoadDialog); + return loadDialog.run(); +} - if (anim_head->blend) - spriteType += RDSPR_BLEND; +void Save_control(void) { //Tony1Apr97 not a joke + Sword2SaveLoadDialog saveDialog(kSaveDialog); + saveDialog.run(); +} - if ((cdt_entry->frameType) & FRAME_FLIPPED) //if the frame is to be flipped (only really applicable to frames using offsets) - spriteType += RDSPR_FLIP; +void Quit_control(void) { //Tony2Apr97 + Sword2MiniDialog quitDialog(149618692); // quit text - 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; + if (!quitDialog.run()) { + // just return to game + return; } - 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; + // close engine systems down + Close_game(); + CloseAppWindow(); + exit(0); +} +void Restart_control(void) { //Tony4Apr97 + uint32 temp_demo_flag; -// Zdebug("w %d h %d", frame_head->width, frame_head->height); + Sword2MiniDialog restartDialog(149618693); // restart text - CreateSurface(sprite, surface); + if (!restartDialog.run()) { + // just return to game + return; + } + // Stop music instantly! (James22aug97) + Kill_music(); - res_man.Res_close(res); //release the anim resource + //in case we were dead - well we're not anymore! + DEAD = 0; -} -//----------------------------------------------------------------------------------------------------------------------- -void Build_surfaces(void) //Tony27March97 -{ + EraseBackBuffer(); + // restart the game + // clear all memory and reset the globals -//setup the control window - Create_surface_image(&panel_sprite, &panel_surface, WINDOW_RES, WINDOW_X, REST_Y, 0); + temp_demo_flag = DEMO; + // remove all resources from memory, including player object and + // global variables + res_man.Remove_all_res(); + // reopen global variables resource & send address to interpreter - + // it won't be moving + SetGlobalInterpreterVariables((int32 *) (res_man.Res_open(1) + sizeof(_standardHeader))); + res_man.Res_close(1); -//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); + DEMO = temp_demo_flag; -//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); + // free all the route memory blocks from previous game + FreeAllRouteMem(); -//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); + // call the same function that first started us up + g_sword2->Start_game(); -//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); + // prime system with a game cycle -//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); + // reset the graphic 'buildit' list before a new logic list + // (see FN_register_frame) + Reset_render_lists(); -//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); + // reset the mouse hot-spot list (see FN_register_mouse and + // FN_register_frame) + Reset_mouse_list(); -//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); + CloseMenuImmediately(); -//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); + // FOR THE DEMO - FORCE THE SCROLLING TO BE RESET! (James29may97) + // - this is taken from FN_init_background + // switch on scrolling (2 means first time on screen) -} -//----------------------------------------------------------------------------------------------------------------------- -void Build_chr_surfaces(void) //tony2Apr97 -{ + this_screen.scroll_flag = 2; - int j; + if (LLogic.Process_session()) + Con_fatal_error("restart 1st cycle failed??"); + // (JEL08oct97) so palette not restored immediately after control + // panel - we want to fade up instead! + this_screen.new_palette = 99; +} -//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 +void Control_error(char* text) { //Tony13May97 + // Print a message on screen. Second parameter is duration. + DisplayMsg((uint8*) text, 0); + // Wait for ESC or mouse click + while (1) { + _mouseEvent *me; + char c; -//set up the chr$ set frame surfaces - chr_sprite.scale=0; - chr_sprite.type= RDSPR_NOCOMPRESSION+RDSPR_TRANS; - chr_sprite.blend= 0; + ServiceWindows(); - 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]); + if (KeyWaiting()) { + ReadKey(&c); + if (c == 27) + break; + } -// 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]); + me = MouseEvent(); + if (me && (me->buttons & RD_LEFTBUTTONDOWN)) + break; + g_sword2->_system->delay_msecs(20); } - res_man.Res_close(controls_font_id); //close font file - res_man.Res_close(red_font_id); //close font file - + // Remove the message. + RemoveMsg(); } -//----------------------------------------------------------------------------------------------------------------------- -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; +int32 ReadOptionSettings(void) { //pete10Jun97 + // settings file is 9 bytes long: + // 1 music volume + // 2 speech volume + // 3 fx volume + // 4 music mute + // 5 speech mute + // 6 fx mute + // 7 graphics level + // 8 subtitles + // 9 object labels + + 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; -//release chr$ set surfaces - for (j=0; j < SIZE_OF_CHAR_SET; j++) - { //normal - DeleteSurface(chr_surface[j]); -// red - DeleteSurface(red_chr_surface[j]); + if (fp->read(buff, 10) != 10) { + delete fp; + delete mgr; + return 2; } -} -//----------------------------------------------------------------------------------------------------------------------- -void Renew_surfaces(void) //Tony27March97 -{ - Kill_surfaces(); - Kill_chr_surfaces(); - Build_surfaces(); - Build_chr_surfaces(); -} -//----------------------------------------------------------------------------------------------------------------------- + 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; +} -//----------------------------------------------------------------------------------------------------------------------- -void Save_control(void) //Tony1Apr97 not a joke -{ -//largely the same as the restore code +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; - 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)&&(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_posStart_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)&&(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; - - 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) - { + if (fp->write(buff, 10) != 10) { delete fp; delete mgr; - return (2); + return 2; } delete fp; delete mgr; - - return (0); + return 0; } +void Option_control(void) { //Pete6Jun97 + Sword2OptionsDialog optionsDialog; -//----------------------------------------------------------------------------------------------------------------------- -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)_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].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) - 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_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; - g_sword2->_sound->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; - g_sword2->_sound->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) - } - } - - - Kill_option_surfaces(); - - return; //just return to game + optionsDialog.run(); + return; } void UpdateGraphicsLevel(uint8 newLevel) { // (James13jun97) diff --git a/sword2/driver/driver96.h b/sword2/driver/driver96.h index 76e654569f..9543e9e58e 100644 --- a/sword2/driver/driver96.h +++ b/sword2/driver/driver96.h @@ -604,14 +604,13 @@ // // --------------------------------------------------------------------------- // -// int32 DrawSurface(_spriteInfo *s, uint32 surface) +// void DrawSurface(_spriteInfo *s, uint32 surface, ScummVM::Rect *clipRect) // -// Draws the sprite surface created earlier. If the surface has been lost, -// it is recreated. +// Draws the sprite surface created earlier. // // --------------------------------------------------------------------------- // -// int32 DeleteSurface(uint32 surface) +// void DeleteSurface(uint32 surface) // // Deletes a surface from video memory. // @@ -1448,8 +1447,8 @@ extern void GetKeyStatus(_drvKeyStatus *s); //----------------------------------------------------------------------------- extern int32 DrawSprite(_spriteInfo *s); extern int32 CreateSurface(_spriteInfo *s, uint8 **surface); -extern int32 DrawSurface(_spriteInfo *s, uint8 *surface); -extern int32 DeleteSurface(uint8 *surface); +extern void DrawSurface(_spriteInfo *s, uint8 *surface, ScummVM::Rect *clipRect = NULL); +extern void DeleteSurface(uint8 *surface); extern int32 OpenLightMask(_spriteInfo *s); extern int32 CloseLightMask(void); //----------------------------------------------------------------------------- diff --git a/sword2/driver/sprite.cpp b/sword2/driver/sprite.cpp index b35a6df9d8..6a2b6364dc 100644 --- a/sword2/driver/sprite.cpp +++ b/sword2/driver/sprite.cpp @@ -235,7 +235,7 @@ // // --------------------------------------------------------------------------- // -// int32 DrawSurface(_spriteInfo *s, uint32 surface) +// int32 DrawSurface(_spriteInfo *s, uint32 surface, ScummVM::Rect *clipRect) // // Draws the sprite surface created earlier. If the surface has been lost, // it is recreated. @@ -1197,9 +1197,8 @@ int32 SoftwareRenderCompressed256(_spriteInfo *s) return 0; } - -// The purpose of this function seems to be to decode a sprite to its -// simplest form in advance. +// The surface functions are only used by the in-game dialogs. Everything +// that isn't needed for them (blending, scaling, etc.) has been removed. int32 CreateSurface(_spriteInfo *s, uint8 **sprite) { uint8 *newSprite; @@ -1211,7 +1210,7 @@ int32 CreateSurface(_spriteInfo *s, uint8 **sprite) { if (s->type & RDSPR_NOCOMPRESSION) { memcpy(*sprite, s->data, s->w * s->h); } else { - if (s->type >> 8 == RDSPR_RLE16 >> 8) { + if ((s->type >> 8) == (RDSPR_RLE16 >> 8)) { if (DecompressRLE16(*sprite, s->data, s->w * s->h, s->colourTable)) { free(*sprite); return RDERR_DECOMPRESSION; @@ -1234,112 +1233,70 @@ int32 CreateSurface(_spriteInfo *s, uint8 **sprite) { *sprite = newSprite; } } + return RD_OK; } - -int32 DrawSurface(_spriteInfo *s, uint8 *surface) { +void DrawSurface(_spriteInfo *s, uint8 *surface, ScummVM::Rect *clipRect) { ScummVM::Rect rd, rs; - uint16 x, y, srcPitch, scale; - uint8 *sprite, *src, *dst; - bool freeSprite = false; - - // FIXME: It should be possible to implement this in terms of the - // DrawSprite() function. - - if (s->type & RDSPR_DISPLAYALIGN) { - rd.top = s->y; - rd.left = s->x; - } else { - rd.top = s->y - scrolly; - rd.left = s->x - scrollx; - } + uint16 x, y, srcPitch; + uint8 *src, *dst; rs.left = 0; rs.right = s->w; rs.top = 0; rs.bottom = s->h; - scale = (s->scale == 0) ? 256 : s->scale; - - if (scale != 256) { - rs.right = s->scaledWidth; - rs.bottom = s->scaledHeight; - srcPitch = s->scaledWidth; - } else { - rs.right = s->w; - rs.bottom = s->h; - srcPitch = s->w; - } + srcPitch = s->w; + rd.top = rs.top + s->y - scrolly; + rd.left = rs.left + s->x - scrollx; rd.right = rd.left + rs.right; rd.bottom = rd.top + rs.bottom; - // Do clipping - if (rd.top < 40) { - rs.top = (40 - rd.top) * 256 / s->scale; - rd.top = 40; - } - if (rd.bottom > 440) { - rs.bottom -= ((rd.bottom - 440) * 256 / s->scale); - rd.bottom = 440; - } - if (rd.left < 0) { - rs.left = (0 - rd.left) * 256 / s->scale; - rd.left = 0; - } - if (rd.right > 640) { - rs.right -= ((rd.right - 640) * 256 / s->scale); - rd.right = 640; - } + if (clipRect) { + if (clipRect->left > rd.left) { + rs.left += (clipRect->left - rd.left); + rd.left = clipRect->left; + } - if (scale != 256) { - sprite = (uint8 *) malloc(s->scaledWidth * s->scaledHeight); - if (!sprite) - return RDERR_OUTOFMEMORY; - - if (scale < 256) { - SquashImage(sprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, surface, s->w, s->w, s->h, NULL); - } else { - StretchImage(sprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, surface, s->w, s->w, s->h, NULL); + if (clipRect->top > rd.top) { + rs.top += (clipRect->top - rd.top); + rd.top = clipRect->top; } - freeSprite = true; - } else - sprite = surface; + if (clipRect->right < rd.right) { + rd.right = clipRect->right; + } - src = sprite + rs.top * srcPitch + rs.left; + if (clipRect->bottom < rd.bottom) { + rd.bottom = clipRect->bottom; + } + + if (rd.width() <= 0 || rd.height() <= 0) + return; + } + + src = surface + rs.top * srcPitch + rs.left; dst = lpBackBuffer + screenWide * rd.top + rd.left; - if (s->type & RDSPR_TRANS) { - for (y = 0; y < rd.bottom - rd.top; y++) { - for (x = 0; x < rd.right - rd.left; x++) { - if (src[x]) - dst[x] = src[x]; - } - src += srcPitch; - dst += screenWide; + // Surfaces are always transparent. + + for (y = 0; y < rd.height(); y++) { + for (x = 0; x < rd.width(); x++) { + if (src[x]) + dst[x] = src[x]; } - } else { - for (y = 0; y < rd.bottom - rd.top; y++) - memcpy(dst, src, screenWide); src += srcPitch; dst += screenWide; } - if (freeSprite) - free(sprite); - - // UploadRect(&rd); + UploadRect(&rd); SetNeedRedraw(); - - return 0; } - -int32 DeleteSurface(uint8 *surface) { +void DeleteSurface(uint8 *surface) { free(surface); - return 0; } #define SCALE_MAXWIDTH 512 @@ -1371,7 +1328,7 @@ int32 DrawSprite(_spriteInfo *s) { freeSprite = true; if (!sprite) return RDERR_OUTOFMEMORY; - if (s->type >> 8 == RDSPR_RLE16 >> 8) { + if ((s->type >> 8) == (RDSPR_RLE16 >> 8)) { if (DecompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) { free(sprite); return RDERR_DECOMPRESSION; @@ -1528,8 +1485,8 @@ int32 DrawSprite(_spriteInfo *s) { src = sprite + rs.top * srcPitch + rs.left; lightMap = lightMask + (rd.top + scrolly - 40) * locationWide + rd.left + scrollx; - for (i = 0; i < rs.bottom - rs.top; i++) { - for (j = 0; j < rs.right - rs.left; j++) { + for (i = 0; i < rs.height(); i++) { + for (j = 0; j < rs.width(); j++) { if (src[j] && lightMap[j]) { uint8 r = ((32 - lightMap[j]) * palCopy[src[j]][0]) >> 5; uint8 g = ((32 - lightMap[j]) * palCopy[src[j]][1]) >> 5; @@ -1551,8 +1508,8 @@ int32 DrawSprite(_spriteInfo *s) { if (s->type & RDSPR_BLEND) { if (renderCaps & RDBLTFX_ALLHARDWARE) { - for (i = 0; i < rs.bottom - rs.top; i++) { - for (j = 0; j < rs.right - rs.left; j++) { + for (i = 0; i < rs.height(); i++) { + for (j = 0; j < rs.width(); j++) { if (src[j] && ((i & 1) == (j & 1))) dst[j] = src[j]; } @@ -1562,8 +1519,8 @@ int32 DrawSprite(_spriteInfo *s) { } else { if (s->blend & 0x01) { red = s->blend >> 8; - for (i = 0; i < rs.bottom - rs.top; i++) { - for (j = 0; j < rs.right - rs.left; j++) { + for (i = 0; i < rs.height(); i++) { + for (j = 0; j < rs.width(); j++) { if (src[j]) { uint8 r = (palCopy[src[j]][0] * red + palCopy[dst[j]][0] * (8 - red)) >> 3; uint8 g = (palCopy[src[j]][1] * red + palCopy[dst[j]][1] * (8 - red)) >> 3; @@ -1591,8 +1548,8 @@ int32 DrawSprite(_spriteInfo *s) { red = palCopy[s->blend >> 8][0]; green = palCopy[s->blend >> 8][0]; blue = palCopy[s->blend >> 8][0]; - for (i = 0; i < rs.bottom - rs.top; i++) { - for (j = 0; j < rs.right - rs.left; j++) { + for (i = 0; i < rs.height(); i++) { + for (j = 0; j < rs.width(); j++) { if (src[j]) { uint8 r = (src[j] * red + (16 - src[j]) * palCopy[dst[j]][0]) >> 4; uint8 g = (src[j] * green + (16 - src[j]) * palCopy[dst[j]][1]) >> 4; @@ -1612,8 +1569,8 @@ int32 DrawSprite(_spriteInfo *s) { } } else { if (s->type & RDSPR_TRANS) { - for (i = 0; i < rs.bottom - rs.top; i++) { - for (j = 0; j < rs.right - rs.left; j++) { + for (i = 0; i < rs.height(); i++) { + for (j = 0; j < rs.width(); j++) { if (src[j]) dst[j] = src[j]; } @@ -1621,8 +1578,8 @@ int32 DrawSprite(_spriteInfo *s) { dst += screenWide; } } else { - for (i = 0; i < rs.bottom - rs.top; i++) { - memcpy(dst, src, rs.right - rs.left); + for (i = 0; i < rs.height(); i++) { + memcpy(dst, src, rs.width()); src += srcPitch; dst += screenWide; } -- cgit v1.2.3