From f891aceee307fa614fcd312b6f567792f1b95ae1 Mon Sep 17 00:00:00 2001 From: Robert Göffringmann Date: Sun, 22 Jun 2003 21:42:59 +0000 Subject: native mt32 support and basic control panel (incomplete) doesn't work with all versions, probably file numbers were changed svn-id: r8632 --- sky/control.cpp | 660 +++++++++++++++++++++++++++++++++++++++++++++++ sky/control.h | 194 ++++++++++++++ sky/logic.cpp | 1 + sky/module.mk | 2 + sky/music/adlibmusic.cpp | 6 + sky/music/adlibmusic.h | 1 + sky/music/gmmusic.cpp | 10 + sky/music/gmmusic.h | 1 + sky/music/mt32music.cpp | 103 +++----- sky/music/mt32music.h | 1 + sky/music/musicbase.cpp | 2 +- sky/music/musicbase.h | 2 + sky/sky.cpp | 15 +- sky/sky.h | 4 + sky/sound.cpp | 2 +- 15 files changed, 934 insertions(+), 70 deletions(-) create mode 100644 sky/control.cpp create mode 100644 sky/control.h (limited to 'sky') diff --git a/sky/control.cpp b/sky/control.cpp new file mode 100644 index 0000000000..491cd2d4da --- /dev/null +++ b/sky/control.cpp @@ -0,0 +1,660 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2003 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "sky/control.h" +#include "sky/skydefs.h" +#include "sky/sky.h" +#include "common/file.h" + +SkyConResource::SkyConResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, uint16 pX, uint16 pY, uint32 pText, uint8 pOnClick, OSystem *system, uint8 *screen) { + + _spriteData = (dataFileHeader*)pSpData; + _numSprites = pNSprites; + _curSprite = pCurSprite; + _x = pX; + _y = pY; + _text = pText; + _onClick = pOnClick; + _system = system; + _screen = screen; +} + +bool SkyConResource::isMouseOver(uint32 mouseX, uint32 mouseY) { + + if ((mouseX >= _x) && (mouseY >= _y) && ((uint16)mouseX <= _x + _spriteData->s_width) && ((uint16)mouseY <= _y + _spriteData->s_height)) + return true; + else + return false; +} + +void SkyConResource::drawToScreen(bool doMask) { + + uint8 *screenPos = _y * GAME_SCREEN_WIDTH + _x + _screen; + uint8 *updatePos = screenPos; + + if (!_spriteData) return; + uint8 *spriteData = ((uint8*)_spriteData) + sizeof(dataFileHeader); + spriteData += _spriteData->s_sp_size * _curSprite; + if (doMask) { + for (uint16 cnty = 0; cnty < _spriteData->s_height; cnty++) { + for (uint16 cntx = 0; cntx < _spriteData->s_width; cntx++) { + if (spriteData[cntx]) screenPos[cntx] = spriteData[cntx]; + } + screenPos += GAME_SCREEN_WIDTH; + spriteData += _spriteData->s_width; + } + } else { + for (uint16 cnty = 0; cnty < _spriteData->s_height; cnty++) { + memcpy(screenPos, spriteData, _spriteData->s_width); + screenPos += GAME_SCREEN_WIDTH; + spriteData += _spriteData->s_width; + } + } + _system->copy_rect(updatePos, GAME_SCREEN_WIDTH, _x, _y, _spriteData->s_width, _spriteData->s_height); +} + +SkyTextResource::SkyTextResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, uint16 pX, uint16 pY, uint32 pText, uint8 pOnClick, OSystem *system, uint8 *screen) : + SkyConResource(pSpData, pNSprites, pCurSprite, pX, pY, pText, pOnClick, system, screen) { + _oldScreen = (uint8*)malloc(PAN_CHAR_HEIGHT * PAN_LINE_WIDTH); + _oldY = 0; + _oldX = GAME_SCREEN_WIDTH; +} + +SkyTextResource::~SkyTextResource(void) { + free(_oldScreen); +} + +void SkyTextResource::drawToScreen(bool doMask) { + + doMask = true; + uint16 cnty, cntx, cpWidth; + if ((_oldX == _x) && (_oldY == _y) && (_spriteData)) return; + if (_oldX < GAME_SCREEN_WIDTH) { + cpWidth = (PAN_LINE_WIDTH > (GAME_SCREEN_WIDTH - _oldX))?(GAME_SCREEN_WIDTH - _oldX):(PAN_LINE_WIDTH); + for (cnty = 0; cnty < PAN_CHAR_HEIGHT; cnty++) + memcpy(_screen + (cnty + _oldY) * GAME_SCREEN_WIDTH + _oldX, _oldScreen + cnty * PAN_LINE_WIDTH, cpWidth); + _system->copy_rect(_screen + _oldY * GAME_SCREEN_WIDTH + _oldX, GAME_SCREEN_WIDTH, _oldX, _oldY, cpWidth, PAN_CHAR_HEIGHT); + } + if (!_spriteData) { + _oldX = GAME_SCREEN_WIDTH; + return; + } + _oldX = _x; + _oldY = _y; + cpWidth = (PAN_LINE_WIDTH > (GAME_SCREEN_WIDTH - _x))?(GAME_SCREEN_WIDTH - _x):(PAN_LINE_WIDTH); + uint8 *screenPos = _screen + _y * GAME_SCREEN_WIDTH + _x; + uint8 *copyDest = _oldScreen; + uint8 *copySrc = ((uint8*)_spriteData) + sizeof(dataFileHeader); + for (cnty = 0; cnty < PAN_CHAR_HEIGHT; cnty++) { + memcpy(copyDest, screenPos, cpWidth); + for (cntx = 0; cntx < PAN_LINE_WIDTH; cntx++) + if (copySrc[cntx]) screenPos[cntx] = copySrc[cntx]; + copySrc += _spriteData->s_width; + copyDest += PAN_LINE_WIDTH; + screenPos += GAME_SCREEN_WIDTH; + } + _system->copy_rect(_screen + _y * GAME_SCREEN_WIDTH + _x, GAME_SCREEN_WIDTH, _x, _y, cpWidth, PAN_CHAR_HEIGHT); +} + +SkyControl::SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, OSystem *system, const char *savePath) { + + _skyScreen = screen; + _skyDisk = disk; + _skyMouse = mouse; + _skyText = text; + _skyMusic = music; + _system = system; + _savePath = savePath; +} + +SkyConResource *SkyControl::createResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, int16 pX, int16 pY, uint32 pText, uint8 pOnClick, uint8 panelType) { + + if (pText) pText += 0x7000; + if (panelType == MAINPANEL) { + pX += MPNL_X; + pY += MPNL_Y; + } else { + pX += SPNL_X; + pY += SPNL_Y; + } + return new SkyConResource(pSpData, pNSprites, pCurSprite, pX, pY, pText, pOnClick, _system, _screenBuf); +} + +void SkyControl::removePanel(void) { + + free(_screenBuf); + free(_sprites.controlPanel); free(_sprites.button); + free(_sprites.buttonDown); free(_sprites.savePanel); + free(_sprites.yesNo); free(_sprites.slide); + free(_sprites.slide2); free(_sprites.slode); + free(_sprites.slode2); free(_sprites.musicBodge); + delete _controlPanel; delete _exitButton; + delete _slide; delete _slide2; + delete _slode; delete _restorePanButton; + delete _savePanButton; delete _dosPanButton; + delete _restartPanButton; delete _fxPanButton; + delete _musicPanButton; delete _bodge; + delete _yesNo; delete _text; +} + +void SkyControl::initPanel(void) { + + _screenBuf = (uint8*)malloc(GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); + memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); + + uint16 volY = (127 - _skyMusic->giveVolume()) / 4 + 59 - MPNL_Y; // volume slider's Y coordinate + + _sprites.controlPanel = _skyDisk->loadFile(60500, NULL); + _sprites.button = _skyDisk->loadFile(60501, NULL); + _sprites.buttonDown = _skyDisk->loadFile(60502, NULL); + _sprites.savePanel = _skyDisk->loadFile(60503, NULL); + _sprites.yesNo = _skyDisk->loadFile(60504, NULL); + _sprites.slide = _skyDisk->loadFile(60505, NULL); + _sprites.slode = _skyDisk->loadFile(60506, NULL); + _sprites.slode2 = _skyDisk->loadFile(60507, NULL); + _sprites.slide2 = _skyDisk->loadFile(60508, NULL); + _sprites.musicBodge = _skyDisk->loadFile(60509, NULL); + + //Main control panel: X Y Text OnClick + _controlPanel = createResource(_sprites.controlPanel, 1, 0, 0, 0, 0, DO_NOTHING, MAINPANEL); + _exitButton = createResource( _sprites.button, 3, 0, 16, 125, 50, EXIT, MAINPANEL); + _slide = createResource( _sprites.slide2, 1, 0, 19, 99, 95, SPEED_SLIDE, MAINPANEL); + _slide2 = createResource( _sprites.slide2, 1, 0, 19,volY, 14, MUSIC_SLIDE, MAINPANEL); + _slode = createResource( _sprites.slode2, 1, 0, 9, 49, 0, DO_NOTHING, MAINPANEL); + _restorePanButton = createResource( _sprites.button, 3, 0, 58, 19, 51, REST_GAME_PANEL, MAINPANEL); + _savePanButton = createResource( _sprites.button, 3, 0, 58, 39, 48, SAVE_GAME_PANEL, MAINPANEL); + _dosPanButton = createResource( _sprites.button, 3, 0, 58, 59, 93, QUIT_TO_DOS, MAINPANEL); + _restartPanButton = createResource( _sprites.button, 3, 0, 58, 79, 94, RESTART, MAINPANEL); + if (SkyState::_systemVars.systemFlags & SF_FX_OFF) + _fxPanButton = createResource( _sprites.button, 3, 0, 58, 99, 86, TOGGLE_FX, MAINPANEL); + else + _fxPanButton = createResource( _sprites.button, 3, 2, 58, 99, 87, TOGGLE_FX, MAINPANEL); + _musicPanButton = createResource( _sprites.button, 3, 0, 58, 119, 35, TOGGLE_MS, MAINPANEL); + _bodge = createResource( _sprites.musicBodge, 2, 1, 98, 115, 0, DO_NOTHING, MAINPANEL); + _yesNo = createResource( _sprites.yesNo, 1, 0, -2, 40, 0, DO_NOTHING, MAINPANEL); + + _text = new SkyTextResource(NULL, 1, 0, 15, 137, 0, DO_NOTHING, _system, _screenBuf); + _controlPanLookList[0] = _exitButton; + _controlPanLookList[1] = _restorePanButton; + _controlPanLookList[2] = _savePanButton; + _controlPanLookList[3] = _dosPanButton; + _controlPanLookList[4] = _restartPanButton; + _controlPanLookList[5] = _fxPanButton; + _controlPanLookList[6] = _musicPanButton; + _controlPanLookList[7] = _slide; + _controlPanLookList[8] = _slide2; + + // save/restore panel + _savePanel = createResource( _sprites.savePanel, 1, 0, 0, 0, 0, DO_NOTHING, SAVEPANEL); + _saveButton = createResource( _sprites.button, 3, 0, 29, 129, 48, SAVE_A_GAME, SAVEPANEL); + _downFastButton = createResource(_sprites.buttonDown, 1, 0, 212, 104, 0, SHIFT_DOWN_FAST, SAVEPANEL); + _downSlowButton = createResource(_sprites.buttonDown, 1, 0, 212, 114, 0, SHIFT_DOWN_SLOW, SAVEPANEL); + _upFastButton = createResource(_sprites.buttonDown, 1, 0, 212, 21, 0, SHIFT_UP_FAST, SAVEPANEL); + _upSlowButton = createResource(_sprites.buttonDown, 1, 0, 212, 10, 0, SHIFT_UP_SLOW, SAVEPANEL); + _quitButton = createResource( _sprites.button, 3, 0, 72, 129, 49, SP_CANCEL, SAVEPANEL); + _restoreButton = createResource( _sprites.button, 3, 0, 29, 129, 51, RESTORE_A_GAME, SAVEPANEL); + + _savePanLookList[0] = _saveButton; + _restorePanLookList[0] = _restoreButton; + _restorePanLookList[1] = _savePanLookList[1] = _downSlowButton; + _restorePanLookList[2] = _savePanLookList[2] = _downFastButton; + _restorePanLookList[3] = _savePanLookList[3] = _upFastButton; + _restorePanLookList[4] = _savePanLookList[4] = _upSlowButton; + _restorePanLookList[5] = _savePanLookList[5] = _quitButton; +} + +void SkyControl::buttonControl(SkyConResource *pButton) { + + if (pButton == NULL) { + if (_textSprite) free(_textSprite); + _textSprite = NULL; + _curButtonText = 0; + _text->setSprite(NULL); + return ; + } + if (_curButtonText != pButton->_text) { + if (_textSprite) free(_textSprite); + _textSprite = NULL; + _curButtonText = pButton->_text; + if (pButton->_text) { + _skyText->getText(pButton->_text); + displayText_t textRes; + textRes = _skyText->displayText(NULL, false, PAN_LINE_WIDTH, 255); + _textSprite = (dataFileHeader*)textRes.textData; + _text->setSprite(_textSprite); + } else _text->setSprite(NULL); + } + _text->setXY(_mouseX + 12, _mouseY - 16); +} + +void SkyControl::animClick(SkyConResource *pButton) { + + if (pButton->_curSprite != pButton->_numSprites -1) { + pButton->_curSprite++; + pButton->drawToScreen(NO_MASK); + _system->update_screen(); + delay(150); + pButton->_curSprite--; + pButton->drawToScreen(NO_MASK); + _system->update_screen(); + } +} + +void SkyControl::drawMainPanel(void) { + + memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); + _system->copy_rect(_screenBuf, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); + _controlPanel->drawToScreen(NO_MASK); + _exitButton->drawToScreen(NO_MASK); + _savePanButton->drawToScreen(NO_MASK); + _restorePanButton->drawToScreen(NO_MASK); + _dosPanButton->drawToScreen(NO_MASK); + _restartPanButton->drawToScreen(NO_MASK); + _fxPanButton->drawToScreen(NO_MASK); + _musicPanButton->drawToScreen(NO_MASK); + _slode->drawToScreen(WITH_MASK); + _slide->drawToScreen(WITH_MASK); + _slide2->drawToScreen(WITH_MASK); + _bodge->drawToScreen(WITH_MASK); +} + +void SkyControl::doControlPanel(void) { + + if (SkyState::isDemo() && (!SkyState::isCDVersion())) { + return ; + } + initPanel(); + + _skyScreen->clearScreen(); + _skyScreen->setPalette(60510); + + drawMainPanel(); + + _skyMouse->spriteMouse(MOUSE_NORMAL,0,0); + bool quitPanel = false; + _lastButton = -1; + _curButtonText = 0; + _textSprite = NULL; + uint16 clickRes = 0; + + while (!quitPanel) { + _text->drawToScreen(WITH_MASK); + _system->update_screen(); + _mouseClicked = false; + delay(50); + if (_keyPressed == 27) { // escape pressed + _mouseClicked = false; + quitPanel = true; + } + bool haveButton = false; + for (uint8 lookCnt = 0; lookCnt < 9; lookCnt++) { + if (_controlPanLookList[lookCnt]->isMouseOver(_mouseX, _mouseY)) { + haveButton = true; + buttonControl(_controlPanLookList[lookCnt]); + if (_mouseClicked && _controlPanLookList[lookCnt]->_onClick) { + clickRes = handleClick(_controlPanLookList[lookCnt]); + buttonControl(NULL); + _text->drawToScreen(WITH_MASK); // flush text restore buffer + drawMainPanel(); + if (clickRes == QUIT_PANEL) quitPanel = true; + } + _mouseClicked = false; + } + } + if (!haveButton) buttonControl(NULL); + + } + memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); + _system->copy_rect(_screenBuf, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); + _system->update_screen(); + _skyScreen->forceRefresh(); + _skyScreen->setPalette((uint8*)SkyState::fetchCompact(SkyState::_systemVars.currentPalette)); + removePanel(); +} + +uint16 SkyControl::handleClick(SkyConResource *pButton) { + + switch(pButton->_onClick) { + case DO_NOTHING: + return 0; + + case REST_GAME_PANEL: + animClick(pButton); + return saveRestorePanel(false); // texts can't be edited + + case SAVE_GAME_PANEL: + animClick(pButton); + return saveRestorePanel(true); // texts can be edited + + case SAVE_A_GAME: + animClick(pButton); + return GAME_SAVED; + + case RESTORE_A_GAME: + animClick(pButton); + return GAME_RESTORED; + + case SP_CANCEL: + animClick(pButton); + return CANCEL_PRESSED; + + case SHIFT_DOWN_FAST: + animClick(pButton); + return shiftDown(FAST); + + case SHIFT_DOWN_SLOW: + animClick(pButton); + return shiftDown(SLOW); + + case SHIFT_UP_FAST: + animClick(pButton); + return shiftUp(FAST); + + case SHIFT_UP_SLOW: + animClick(pButton); + return shiftUp(SLOW); + + case SPEED_SLIDE: + return 0; + + case MUSIC_SLIDE: + _mouseClicked = true; + return doMusicSlide(); + + case TOGGLE_FX: + return toggleFx(pButton); + + case TOGGLE_MS: + return 0; + + case EXIT: + animClick(pButton); + return QUIT_PANEL; + + case RESTART: + animClick(pButton); + return 0; + + case QUIT_TO_DOS: + animClick(pButton); + return 0; + + default: + error("SkyControl::handleClick: unknown routine: %X\n",pButton->_onClick); + } +} + +uint16 SkyControl::doMusicSlide(void) { + + int ofsY = _slide2->_y - _mouseY; + uint8 volume; + while (_mouseClicked) { + delay(50); + int newY = ofsY + _mouseY; + if (newY < 59) newY = 59; + if (newY > 91) newY = 91; + if (newY != _slide2->_y) { + _slode->drawToScreen(NO_MASK); + _slide2->setXY(_slide2->_x, (uint16)newY); + _slide2->drawToScreen(WITH_MASK); + _slide->drawToScreen(WITH_MASK); + volume = (newY - 59) * 4; + if (volume >= 128) volume = 0; + else volume = 127 - volume; + _skyMusic->setVolume(volume); + } + buttonControl(_slide2); + _text->drawToScreen(WITH_MASK); + _system->update_screen(); + } + return 0; +} + +uint16 SkyControl::toggleFx(SkyConResource *pButton) { + + SkyState::_systemVars.systemFlags ^= SF_FX_OFF; + if (SkyState::_systemVars.systemFlags & SF_FX_OFF) { + pButton->_curSprite = 0; + pButton->_text = 0x7000 + 86; + } else { + pButton->_curSprite = 2; + pButton->_text = 0x7000 + 87; + } + pButton->drawToScreen(WITH_MASK); + buttonControl(pButton); + _system->update_screen(); + return TOGGLED; +} + +uint16 SkyControl::shiftDown(uint8 speed) { + + if (speed == SLOW) { + if (_firstText >= MAX_SAVE_GAMES - MAX_ON_SCREEN) return 0; + _firstText++; + } else { + if (_firstText <= MAX_SAVE_GAMES - 2 * MAX_ON_SCREEN) + _firstText += MAX_ON_SCREEN; + else if (_firstText < MAX_SAVE_GAMES - MAX_ON_SCREEN) + _firstText = MAX_SAVE_GAMES - MAX_ON_SCREEN; + else return 0; + } + return SHIFTED; +} + +uint16 SkyControl::shiftUp(uint8 speed) { + + if (speed == SLOW) { + if (_firstText > 0) _firstText--; + else return 0; + } else { + if (_firstText >= MAX_ON_SCREEN) _firstText -= MAX_ON_SCREEN; + else if (_firstText > 0) _firstText = 0; + else return 0; + } + return SHIFTED; +} + +uint16 SkyControl::saveRestorePanel(bool allowEdit) { + + buttonControl(NULL); + _text->drawToScreen(WITH_MASK); // flush text restore buffer + + SkyConResource **lookList; + uint16 cnt; + if (allowEdit) lookList = _savePanLookList; + else lookList = _restorePanLookList; + + uint8 *saveGameTexts = (uint8*)malloc(MAX_SAVE_GAMES * MAX_TEXT_LEN); + dataFileHeader *textSprites[MAX_ON_SCREEN]; + _firstText = 0; + + _savePanel->drawToScreen(NO_MASK); + _quitButton->drawToScreen(NO_MASK); + + loadSaveDescriptions(saveGameTexts); + setUpGameSprites(saveGameTexts, textSprites, _firstText); + + uint16 selectedGame = 0; + + bool quitPanel = false; + bool refreshNames = true; + uint16 clickRes; + while (!quitPanel) { + if (refreshNames) { + showSprites(textSprites); + refreshNames = false; + } + + _text->drawToScreen(WITH_MASK); + _system->update_screen(); + _mouseClicked = false; + delay(50); + if (_keyPressed == 27) { // escape pressed + _mouseClicked = false; + clickRes = CANCEL_PRESSED; + quitPanel = true; + } + bool haveButton = false; + for (uint16 cnt = 0; cnt < 6; cnt++) + if (lookList[cnt]->isMouseOver(_mouseX, _mouseY)) { + buttonControl(lookList[cnt]); + haveButton = true; + + if (_mouseClicked && lookList[cnt]->_onClick) { + _mouseClicked = false; + + clickRes = handleClick(lookList[cnt]); + if ((clickRes == CANCEL_PRESSED) || (clickRes == GAME_SAVED) || + (clickRes == GAME_RESTORED) || (clickRes == NO_DISK_SPACE)) + quitPanel = true; + if (clickRes == SHIFTED) { + setUpGameSprites(saveGameTexts, textSprites, _firstText); + refreshNames = true; + } + } + } + if (_mouseClicked) { + if ((_mouseX >= GAME_NAME_X) && (_mouseX <= GAME_NAME_X + PAN_LINE_WIDTH) && + (_mouseY >= GAME_NAME_Y) && (_mouseY <= GAME_NAME_Y + PAN_CHAR_HEIGHT * MAX_ON_SCREEN)) { + + selectedGame = (_mouseY - GAME_NAME_Y) / PAN_CHAR_HEIGHT + _firstText; + } + } + if (!haveButton) buttonControl(NULL); + + } + + for (cnt = 0; cnt < MAX_ON_SCREEN; cnt++) + free(textSprites[cnt]); + + free(saveGameTexts); + + return clickRes; +} + +void SkyControl::setUpGameSprites(uint8 *nameBuf, dataFileHeader **nameSprites, uint16 firstNum) { + + nameBuf += firstNum * MAX_TEXT_LEN; + + for (uint16 cnt = 0; cnt < MAX_ON_SCREEN; cnt++) { + displayText_t textSpr = _skyText->displayText((char*)nameBuf, NULL, false, PAN_LINE_WIDTH, 37); + nameBuf += MAX_TEXT_LEN; + nameSprites[cnt] = (dataFileHeader*)textSpr.textData; + } +} + +void SkyControl::showSprites(dataFileHeader **nameSprites) { + + SkyConResource *drawResource = new SkyConResource(NULL, 1, 0, 0, 0, 0, 0, _system, _screenBuf); + for (uint16 cnt = 0; cnt < MAX_ON_SCREEN; cnt++) { + drawResource->setSprite(nameSprites[cnt]); + drawResource->setXY(GAME_NAME_X, GAME_NAME_Y + cnt * PAN_CHAR_HEIGHT); + drawResource->drawToScreen(NO_MASK); + } + delete drawResource; +} + +void SkyControl::loadSaveDescriptions(uint8 *destBuf) { + + memset(destBuf, 0, MAX_SAVE_GAMES * MAX_TEXT_LEN); + + File *inf = new File(); + inf->open("SKY.SAV",_savePath); + if (inf->isOpen()) { + uint8 *tmpBuf = (uint8*)malloc(inf->size()); + inf->read(tmpBuf, inf->size()); + uint8 *destPos = destBuf; + uint8 *inPos = tmpBuf; + for (uint16 cnt = 0; cnt < MAX_SAVE_GAMES; cnt++) { + sprintf((char*)destPos,"%3d: ", cnt + 1); + uint8 nameCnt = 0; + while (destPos[nameCnt + 5] = inPos[nameCnt]) nameCnt++; + destPos += MAX_TEXT_LEN; + } + free(tmpBuf); + inf->close(); + } else { + uint8 *destPos = destBuf; + for (uint16 cnt = 0; cnt < MAX_SAVE_GAMES; cnt++) { + sprintf((char*)destPos,"%3d: ", cnt + 1); + destPos += MAX_TEXT_LEN; + } + } +} + +void SkyControl::delay(unsigned int amount) { + + OSystem::Event event; + + uint32 start = _system->get_msecs(); + uint32 cur = start; + _keyPressed = 0; //reset + + do { + while (_system->poll_event(&event)) { + switch (event.event_code) { + case OSystem::EVENT_KEYDOWN: + // Make sure backspace works right (this fixes a small issue on OS X) + if (event.kbd.keycode == 8) + _keyPressed = 8; + else + _keyPressed = (byte)event.kbd.ascii; + break; + + case OSystem::EVENT_MOUSEMOVE: + _mouseX = event.mouse.x; + _mouseY = event.mouse.y; + _system->set_mouse_pos(_mouseX, _mouseY); + break; + + case OSystem::EVENT_LBUTTONDOWN: + _mouseClicked = true; +#ifdef _WIN32_WCE + _mouseX = event.mouse.x; + _mouseY = event.mouse.y; +#endif + break; + + case OSystem::EVENT_LBUTTONUP: + _mouseClicked = false; + break; + + case OSystem::EVENT_RBUTTONDOWN: + break; + + case OSystem::EVENT_QUIT: + _system->quit(); + break; + + default: + break; + } + } + + uint this_delay = 20; // 1? + if (this_delay > amount) + this_delay = amount; + + if (this_delay > 0) _system->delay_msecs(this_delay); + + cur = _system->get_msecs(); + } while (cur < start + amount); +} diff --git a/sky/control.h b/sky/control.h new file mode 100644 index 0000000000..d8ef8d621f --- /dev/null +++ b/sky/control.h @@ -0,0 +1,194 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2003 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#ifndef CONTROL_H +#define CONTROL_H + +#include "common/stdafx.h" +#include "common/scummsys.h" +#include "sky/struc.h" +#include "common/engine.h" +#include "sky/screen.h" +#include "sky/disk.h" +#include "sky/mouse.h" + +#define MAX_SAVE_GAMES 999 +#define MAX_TEXT_LEN 80 +#define PAN_LINE_WIDTH 184 +#define PAN_CHAR_HEIGHT 12 +#define MPNL_X 60 // Main Panel +#define MPNL_Y 10 + +#define SPNL_X 20 // Save Panel +#define SPNL_Y 20 +#define SP_HEIGHT 149 +#define SP_TOP_GAP 12 +#define SP_BOT_GAP 27 + +#define GAME_NAME_X (SPNL_X + 18) // x coordinate of game names +#define GAME_NAME_Y (SPNL_Y + SP_TOP_GAP) // start y coord of game names +#define MAX_ON_SCREEN ((SP_HEIGHT - SP_TOP_GAP - SP_BOT_GAP) / PAN_CHAR_HEIGHT) // no of save games on screen +#define CP_PANEL 60400 // main panel sprite + +#define CHARACTER_LIST " ,().='-&+!?\"" // list of allowed characters + +#define MAINPANEL 0 +#define SAVEPANEL 1 + +#define NO_MASK false +#define WITH_MASK true + +// resource's onClick routines +#define DO_NOTHING 0 +#define REST_GAME_PANEL 1 +#define SAVE_GAME_PANEL 2 +#define SAVE_A_GAME 3 +#define RESTORE_A_GAME 4 +#define SP_CANCEL 5 +#define SHIFT_DOWN_FAST 6 +#define SHIFT_DOWN_SLOW 7 +#define SHIFT_UP_FAST 8 +#define SHIFT_UP_SLOW 9 +#define SPEED_SLIDE 10 +#define MUSIC_SLIDE 11 +#define TOGGLE_FX 12 +#define TOGGLE_MS 13 +#define EXIT 14 +#define RESTART 15 +#define QUIT_TO_DOS 16 + +// onClick return codes +#define CANCEL_PRESSED 100 +#define NAME_TOO_SHORT 101 +#define GAME_SAVED 102 +#define SHIFTED 103 +#define TOGGLED 104 +#define RESTARTED 105 +#define GAME_RESTORED 106 +#define RESTORE_FAILED 107 +#define NO_DISK_SPACE 108 +#define SPEED_CHANGED 109 +#define QUIT_PANEL 110 + +#define SLOW 0 +#define FAST 1 + +class SkyConResource { +public: + SkyConResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, uint16 pX, uint16 pY, uint32 pText, uint8 pOnClick, OSystem *system, uint8 *screen); + virtual ~SkyConResource(void) {}; + void setSprite(void *pSpData) { _spriteData = (dataFileHeader*)pSpData; }; + void setText(uint32 pText) { if (pText) _text = pText + 0x7000; else _text = 0; }; + void setXY(uint16 x, uint16 y) { _x = x; _y = y; }; + bool isMouseOver(uint32 mouseX, uint32 mouseY); + virtual void drawToScreen(bool doMask); + + dataFileHeader *_spriteData; + uint32 _numSprites, _curSprite; + uint16 _x, _y; + uint32 _text; + uint8 _onClick; + OSystem *_system; + uint8 *_screen; +private: +}; + +class SkyTextResource : public SkyConResource { +public: + SkyTextResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, uint16 pX, uint16 pY, uint32 pText, uint8 pOnClick, OSystem *system, uint8 *screen); + virtual ~SkyTextResource(void); + virtual void drawToScreen(bool doMask); +private: + uint16 _oldX, _oldY; + uint8 *_oldScreen; +}; + +class SkyControl { +public: + SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, OSystem *system, const char *savePath); + void doControlPanel(void); + +private: + void initPanel(void); + void removePanel(void); + void drawMainPanel(void); + void delay(unsigned int amount); + void buttonControl(SkyConResource *pButton); + void loadSaveDescriptions(uint8 *destBuf); + void setUpGameSprites(uint8 *nameBuf, dataFileHeader **nameSprites, uint16 firstNum); + void showSprites(dataFileHeader **nameSprites); + void animClick(SkyConResource *pButton); + uint16 doMusicSlide(void); + uint16 handleClick(SkyConResource *pButton); + uint16 toggleFx(SkyConResource *pButton); + uint16 shiftDown(uint8 speed); + uint16 shiftUp(uint8 speed); + const char *_savePath; + + uint16 saveRestorePanel(bool allowEdit); + + SkyScreen *_skyScreen; + SkyDisk *_skyDisk; + SkyMouse *_skyMouse; + SkyText *_skyText; + SkyMusicBase *_skyMusic; + OSystem *_system; + int _mouseX, _mouseY; + bool _mouseClicked; + byte _keyPressed; + + SkyConResource *createResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, int16 pX, int16 pY, uint32 pText, uint8 pOnClick, uint8 panelType); + + struct { + uint8 *controlPanel; + uint8 *button; + uint8 *buttonDown; + uint8 *savePanel; + uint8 *yesNo; + uint8 *slide; + uint8 *slode; + uint8 *slode2; + uint8 *slide2; + uint8 *musicBodge; + } _sprites; + + uint8 *_screenBuf; + int _lastButton; + uint32 _curButtonText; + uint16 _firstText; + + dataFileHeader *_textSprite; + SkyTextResource *_text; + + SkyConResource *_controlPanel, *_exitButton, *_slide, *_slide2, *_slode; + SkyConResource *_restorePanButton, *_savePanButton, *_dosPanButton, *_restartPanButton, *_fxPanButton, *_musicPanButton; + SkyConResource *_bodge, *_yesNo; + SkyConResource *_controlPanLookList[9]; + + //- Save/restore panel + SkyConResource *_savePanel; + SkyConResource *_saveButton, *_downFastButton, *_downSlowButton; + SkyConResource *_upFastButton, *_upSlowButton, *_quitButton, *_restoreButton; + + SkyConResource *_savePanLookList[6], *_restorePanLookList[6]; +}; + +#endif // CONTROL_H diff --git a/sky/logic.cpp b/sky/logic.cpp index 4510c1aba0..5718aefa57 100644 --- a/sky/logic.cpp +++ b/sky/logic.cpp @@ -2292,6 +2292,7 @@ bool SkyLogic::fnFadeDown(uint32 a, uint32 b, uint32 c) { } bool SkyLogic::fnFadeUp(uint32 a, uint32 b, uint32 c) { + SkyState::_systemVars.currentPalette = a; _skyScreen->fnFadeUp(a,b); return true; } diff --git a/sky/module.mk b/sky/module.mk index 1ca2fd56a6..efb2a8d01d 100644 --- a/sky/module.mk +++ b/sky/module.mk @@ -16,10 +16,12 @@ MODULE_OBJS = \ sky/sound.o \ sky/text.o \ sky/introimg.o \ + sky/control.o \ sky/music/adlibchannel.o \ sky/music/adlibmusic.o \ sky/music/gmchannel.o \ sky/music/gmmusic.o \ + sky/music/mt32music.o \ sky/music/musicbase.o \ # Include common rules diff --git a/sky/music/adlibmusic.cpp b/sky/music/adlibmusic.cpp index 46b72e7f03..827ffa8743 100644 --- a/sky/music/adlibmusic.cpp +++ b/sky/music/adlibmusic.cpp @@ -44,6 +44,12 @@ SkyAdlibMusic::~SkyAdlibMusic(void) { YM3812Shutdown(); } +void SkyAdlibMusic::setVolume(uint8 volume) { + + _musicVolume = volume; + _mixer->setMusicVolume(_musicVolume << 1); +} + void SkyAdlibMusic::premixerCall(int16 *buf, uint len) { if (_musicData == NULL) { diff --git a/sky/music/adlibmusic.h b/sky/music/adlibmusic.h index 4fb8fea7fb..8a1bb2c169 100644 --- a/sky/music/adlibmusic.h +++ b/sky/music/adlibmusic.h @@ -33,6 +33,7 @@ class SkyAdlibMusic : public SkyMusicBase { public: SkyAdlibMusic(SoundMixer *pMixer, SkyDisk *pSkyDisk); ~SkyAdlibMusic(void); + virtual void setVolume(uint8 volume); private: SoundMixer *_mixer; uint8 *_initSequence; diff --git a/sky/music/gmmusic.cpp b/sky/music/gmmusic.cpp index 92ea1e4954..78bf349a04 100644 --- a/sky/music/gmmusic.cpp +++ b/sky/music/gmmusic.cpp @@ -47,6 +47,16 @@ SkyGmMusic::~SkyGmMusic(void) { delete _midiDrv; } +void SkyGmMusic::setVolume(uint8 volume) { + + uint8 sysEx[6]; + _musicVolume = volume; + if (volume > 0) volume = (volume * 2) / 3 + 43; // GM synths behave kinda logarithmic + sysEx[0] = 0x7F; sysEx[1] = 0x7F; sysEx[2] = 0x04; sysEx[3] = 0x01; + sysEx[4] = 0; sysEx[5] = volume & 0x7F; + _midiDrv->sysEx(sysEx, 6); +} + void SkyGmMusic::timerCall(void) { // midi driver polls hundred times per sec. We only want 50 times. diff --git a/sky/music/gmmusic.h b/sky/music/gmmusic.h index b3dca05b39..6c9cd0b25c 100644 --- a/sky/music/gmmusic.h +++ b/sky/music/gmmusic.h @@ -32,6 +32,7 @@ class SkyGmMusic : public SkyMusicBase { public: SkyGmMusic(MidiDriver *pMidiDrv, SkyDisk *pSkyDisk); ~SkyGmMusic(void); + virtual void setVolume(uint8 volume); private: static void passTimerFunc(void *param); void timerCall(void); diff --git a/sky/music/mt32music.cpp b/sky/music/mt32music.cpp index 03f3c80a77..1a9b167438 100644 --- a/sky/music/mt32music.cpp +++ b/sky/music/mt32music.cpp @@ -58,6 +58,15 @@ void SkyMT32Music::timerCall(void) { pollMusic(); } +void SkyMT32Music::setVolume(uint8 volume) { + + uint8 sysEx[6]; + _musicVolume = volume; + sysEx[0] = 0x7F; sysEx[1] = 0x7F; sysEx[2] = 0x04; sysEx[3] = 0x01; + sysEx[4] = 0; sysEx[5] = volume & 0x7F; + _midiDrv->sysEx(sysEx, 6); +} + void SkyMT32Music::setupPointers(void) { _musicDataLoc = (_musicData[0x7DD] << 8) | _musicData[0x7DC]; @@ -78,70 +87,50 @@ void SkyMT32Music::setupChannels(uint8 *channelData) { bool SkyMT32Music::processPatchSysEx(uint8 *sysExData) { + uint8 sysExBuf[15]; uint8 crc = 0; if (sysExData[0] & 0x80) return false; - uint8 patchNum = sysExData[0]; - sysExData++; - uint8 timbreGroup = sysExData[0] >> 6; - uint8 timbreNumber = sysExData[0] & 0x3F; - uint8 keyShift = sysExData[1] & 0x3F; - uint8 fineTune = sysExData[2] & 0x7F; - uint8 benderRange = sysExData[3] & 0x7F; - uint8 assignMode = sysExData[1] >> 6; - uint8 reverbSwitch = sysExData[2] >> 7; - - _midiDrv->send(MIDI_PACK(0xF0, 0x41, 0x10, 0x16)); - _midiDrv->send(MIDI_PACK(0x12, 5, patchNum >> 4, (patchNum & 0xF) << 3)); - - crc -= 5 + (patchNum >> 4) + ((patchNum & 0xF) << 3); - crc -= timbreGroup + timbreNumber + keyShift + fineTune; - crc -= benderRange + assignMode + reverbSwitch; - - _midiDrv->send(MIDI_PACK(timbreGroup, timbreNumber, keyShift, fineTune)); - _midiDrv->send(MIDI_PACK(benderRange, assignMode, reverbSwitch, crc)); - _midiDrv->send(0xF7); - - debug(3," Patch %02X:\n",patchNum); - debug(3," Timbre Group: %d\n",timbreGroup); - debug(3," Timbre Number: %d\n",timbreNumber); - debug(3," Key Shift: %d\n",keyShift); - debug(3," Fine Tune: %d\n",fineTune); - debug(3," Bender Range: %d\n",benderRange); - debug(3," Assign Mode: %d\n",assignMode); - debug(3," Reverb Switch: %d\n\n",reverbSwitch); + // decompress data from stream + sysExBuf[0] = 0x41; sysExBuf[1] = 0x10; sysExBuf[2] = 0x16; sysExBuf[3] = 0x12; sysExBuf[4] = 0x5; + sysExBuf[5] = sysExData[0] >> 4; // patch offset part 1 + sysExBuf[6] = (sysExData[0] & 0xF) << 3; // patch offset part 2 + sysExBuf[7] = sysExData[1] >> 6; // timbre group + sysExBuf[8] = sysExData[1] & 0x3F; // timbre num + sysExBuf[9] = sysExData[2] & 0x3F; // key shift + sysExBuf[10] = sysExData[3] & 0x7F; // fine tune + sysExBuf[11] = sysExData[4] & 0x7F; // bender range + sysExBuf[12] = sysExData[2] >> 6; // assign mode + sysExBuf[13] = sysExData[3] >> 7; // reverb switch + for (uint8 cnt = 4; cnt < 14; cnt++) + crc -= sysExBuf[cnt]; + sysExBuf[14] = crc; // crc + _midiDrv->sysEx(sysExBuf, 15); return true; } void SkyMT32Music::startDriver(void) { - _midiDrv->send(0xFF); // reset midi device - // setup timbres and patches using SysEx data uint8* sysExData = _sysExSequence; uint8 timbreNum = sysExData[0]; uint8 cnt, crc; - uint32 sysComb; sysExData++; + uint8 sendBuf[256]; + uint8 len; + sendBuf[0] = 0x41; sendBuf[1] = 0x10; sendBuf[2] = 0x16; sendBuf[3] = 0x12; for (cnt = 0; cnt < timbreNum; cnt++) { + len = 7; crc = 0; - _midiDrv->send(MIDI_PACK(0xF0, 0x41, 0x10, 0x16)); - //- sendTimbreAddress - sysComb = (0x2 << 16) | (sysExData[0] << 8) | 0xA; + // Timbre address + sendBuf[4] = 0x8 | (sysExData[0] >> 6); + sendBuf[5] = (sysExData[0] & 0x3F) << 1; + sendBuf[6] = 0xA; sysExData++; - uint8 sysByte1 = (uint8)(sysComb >> 14); - uint8 sysByte2 = (uint8)((sysComb & 0x3FFF) >> 7); - uint8 sysByte3 = (uint8)(sysComb & 0x7F); - _midiDrv->send(MIDI_PACK(0x12, sysByte1, sysByte2, sysByte3)); - debug(3,"InitBySysEx: Timbre address: %02X:%02X:%02X (%02X)\n",sysByte1,sysByte2,sysByte3,(sysExData-1)[0]); - crc -= sysByte1 + sysByte2 + sysByte3; - //- sendTimbreData + crc -= sendBuf[4] + sendBuf[5] + sendBuf[6]; uint8 dataLen = sysExData[0]; - debug(3,"[%02X]",dataLen); sysExData++; - uint32 nextSend = 0; - uint8 bytesInSend = 0; - debug(3," Timbre Data:"); + // Timbre data: do { uint8 rlVal = 1; uint8 codeVal = sysExData[0]; @@ -154,27 +143,15 @@ void SkyMT32Music::startDriver(void) { dataLen--; } for (uint8 cnt = 0; cnt < rlVal; cnt++) { - nextSend |= codeVal << (bytesInSend << 3); + sendBuf[len] = codeVal; + len++; crc -= codeVal; - debug(3," %02X",codeVal); - bytesInSend++; - if (bytesInSend == 4) { - _midiDrv->send(nextSend); - nextSend = bytesInSend = 0; - } } dataLen--; } while (dataLen > 0); - crc &= 0x7F; - debug(3," %02X F7\n",crc); - nextSend |= crc << (bytesInSend << 3); - bytesInSend++; - if (bytesInSend == 4) { - _midiDrv->send(nextSend); - nextSend = bytesInSend = 0; - } - nextSend |= 0xF7 << (bytesInSend << 3); - _midiDrv->send(nextSend); + sendBuf[len] = crc & 0x7F; + len++; + _midiDrv->sysEx(sendBuf, len); } while (processPatchSysEx(sysExData)) diff --git a/sky/music/mt32music.h b/sky/music/mt32music.h index 76b2a18fc5..e28d3d5373 100644 --- a/sky/music/mt32music.h +++ b/sky/music/mt32music.h @@ -36,6 +36,7 @@ private: static void passTimerFunc(void *param); void timerCall(void); bool processPatchSysEx(uint8 *sysExData); + virtual void setVolume(uint8 volume); bool _ignoreNextPoll; uint8 *_sysExSequence; diff --git a/sky/music/musicbase.cpp b/sky/music/musicbase.cpp index d03edbb4f2..da872f6cf1 100644 --- a/sky/music/musicbase.cpp +++ b/sky/music/musicbase.cpp @@ -43,7 +43,7 @@ void SkyMusicBase::loadSection(uint8 pSection) _allowedCommands = 0; _musicTempo0 = 0x78; // init constants taken from idb file, area ~0x1060 _musicTempo1 = 0xC0; - _musicVolume = 0x100; + _musicVolume = 127; _onNextPoll.doReInit = false; _onNextPoll.doStopMusic = false; _onNextPoll.musicToProcess = 0; diff --git a/sky/music/musicbase.h b/sky/music/musicbase.h index cae59616a8..e237da9e71 100644 --- a/sky/music/musicbase.h +++ b/sky/music/musicbase.h @@ -48,6 +48,8 @@ public: void loadSection(uint8 pSection); void musicCommand(uint16 command); void startMusic(uint16 param) { _onNextPoll.musicToProcess = param & 0xF; }; // 4 + virtual void setVolume(uint8 volume) = 0; + uint8 giveVolume(void) { return (uint8)_musicVolume; }; protected: diff --git a/sky/sky.cpp b/sky/sky.cpp index 846e78fce2..666699f6f0 100644 --- a/sky/sky.cpp +++ b/sky/sky.cpp @@ -141,6 +141,10 @@ void SkyState::go() { while (1) { delay(50); + if ((_key_pressed == 27) || (_key_pressed == 63)) { // 27 = escape, 63 = F5 + _key_pressed = 0; + _skyControl->doControlPanel(); + } _skyMouse->mouseEngine((uint16)_sdl_mouse_x, (uint16)_sdl_mouse_y); _skyLogic->engine(); _skyScreen->recreate(); @@ -152,8 +156,6 @@ void SkyState::go() { void SkyState::initialise(void) { - //initialise_memory(); - _skyDisk = new SkyDisk(_gameDataPath); _skySound = new SkySound(_mixer, _skyDisk); @@ -164,7 +166,10 @@ void SkyState::initialise(void) { _skyMusic = new SkyAdlibMusic(_mixer, _skyDisk); } else { _systemVars.systemFlags |= SF_ROLAND; - _skyMusic = new SkyGmMusic(_detector->createMidi(), _skyDisk); + if (_detector->_native_mt32) + _skyMusic = new SkyMT32Music(_detector->createMidi(), _skyDisk); + else + _skyMusic = new SkyGmMusic(_detector->createMidi(), _skyDisk); } _systemVars.systemFlags |= SF_PLAY_VOCS; @@ -174,14 +179,14 @@ void SkyState::initialise(void) { initVirgin(); initItemList(); - //initScript(); - //initialiseRouter(); loadFixedItems(); _skyLogic = new SkyLogic(_skyScreen, _skyDisk, _skyText, _skyMusic, _skyMouse, _skySound); _skyMouse->useLogicInstance(_skyLogic); _timer = Engine::_timer; // initialize timer *after* _skyScreen has been initialized. _timer->installProcedure(&timerHandler, 1000000 / 50); //call 50 times per second + + _skyControl = new SkyControl(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _system, getSavePath()); } void SkyState::initItemList() { diff --git a/sky/sky.h b/sky/sky.h index 6fdcecd499..7eb7c1db08 100644 --- a/sky/sky.h +++ b/sky/sky.h @@ -37,6 +37,8 @@ #include "sky/music/gmmusic.h" #include "sky/music/mt32music.h" #include "sky/mouse.h" +#include "sky/control.h" +#include "common/config-file.h" struct SystemVars { uint32 systemFlags; @@ -51,6 +53,7 @@ struct SystemVars { class SkyLogic; class SkyScreen; +class SkyControl; class SkyState : public Engine { void errorString(const char *buf_input, char *buf_output); @@ -82,6 +85,7 @@ protected: SkyLogic *_skyLogic; SkyMouse *_skyMouse; SkyScreen *_skyScreen; + SkyControl *_skyControl; SkyMusicBase *_skyMusic; GameDetector *_detector; // necessary for music diff --git a/sky/sound.cpp b/sky/sound.cpp index ab7a866a63..b44cbc2fa8 100644 --- a/sky/sound.cpp +++ b/sky/sound.cpp @@ -1101,7 +1101,7 @@ void SkySound::fnPauseFx(void) { } bool SkySound::fnStartFx(uint32 sound) { - if (sound < 256 || sound > MAX_FX_NUMBER || _sfxPaused) + if (sound < 256 || sound > MAX_FX_NUMBER || _sfxPaused || (SkyState::_systemVars.systemFlags & SF_FX_OFF)) return true; uint8 screen = (uint8)(SkyLogic::_scriptVariables[SCREEN] & 0xff); -- cgit v1.2.3