diff options
-rw-r--r-- | sky/control.cpp | 58 | ||||
-rw-r--r-- | sky/control.h | 2 | ||||
-rw-r--r-- | sky/disk.cpp | 4 | ||||
-rw-r--r-- | sky/intro.cpp | 3 | ||||
-rw-r--r-- | sky/logic.cpp | 11 | ||||
-rw-r--r-- | sky/logic.h | 1 | ||||
-rw-r--r-- | sky/music/adlibchannel.cpp | 2 | ||||
-rw-r--r-- | sky/music/adlibmusic.cpp | 10 | ||||
-rw-r--r-- | sky/music/adlibmusic.h | 1 | ||||
-rw-r--r-- | sky/music/gmmusic.cpp | 5 | ||||
-rw-r--r-- | sky/music/gmmusic.h | 1 | ||||
-rw-r--r-- | sky/music/musicbase.cpp | 43 | ||||
-rw-r--r-- | sky/music/musicbase.h | 12 | ||||
-rw-r--r-- | sky/sky.cpp | 57 | ||||
-rw-r--r-- | sky/sky.h | 2 | ||||
-rw-r--r-- | sky/skydefs.h | 1 | ||||
-rw-r--r-- | sky/sound.cpp | 29 | ||||
-rw-r--r-- | sky/sound.h | 2 | ||||
-rw-r--r-- | sky/struc.h | 1 | ||||
-rw-r--r-- | sky/text.cpp | 264 | ||||
-rw-r--r-- | sky/text.h | 47 |
21 files changed, 219 insertions, 337 deletions
diff --git a/sky/control.cpp b/sky/control.cpp index b10809fda4..c5139ca35f 100644 --- a/sky/control.cpp +++ b/sky/control.cpp @@ -182,10 +182,9 @@ void ControlStatus::setToText(const char *newText) { } void ControlStatus::setToText(uint16 textNum) { - _skyText->getText(textNum); if (_textData) free(_textData); - displayText_t disText = _skyText->displayText(NULL, true, STATUS_WIDTH, 255); + displayText_t disText = _skyText->displayText(textNum, NULL, true, STATUS_WIDTH, 255); _textData = (dataFileHeader *)disText.textData; _statusText->setSprite(_textData); _statusText->drawToScreen(WITH_MASK); @@ -338,12 +337,10 @@ void Control::buttonControl(ConResource *pButton) { _curButtonText = pButton->_text; if (pButton->_text) { displayText_t textRes; - if (pButton->_text == 0xFFFF) { // text for autosave button + if (pButton->_text == 0xFFFF) // text for autosave button textRes = _skyText->displayText(autoSave, NULL, false, PAN_LINE_WIDTH, 255); - } else { - _skyText->getText(pButton->_text); - textRes = _skyText->displayText(NULL, false, PAN_LINE_WIDTH, 255); - } + else + textRes = _skyText->displayText(pButton->_text, NULL, false, PAN_LINE_WIDTH, 255); _textSprite = (dataFileHeader *)textRes.textData; _text->setSprite(_textSprite); } else @@ -475,7 +472,7 @@ void Control::doControlPanel(void) { _textSprite = NULL; uint16 clickRes = 0; - while (!quitPanel) { + while (!quitPanel && !SkyEngine::_systemVars.quitGame) { _text->drawToScreen(WITH_MASK); _system->updateScreen(); _mouseClicked = false; @@ -501,12 +498,13 @@ void Control::doControlPanel(void) { _mouseClicked = false; } } - if (!haveButton) buttonControl(NULL); - + if (!haveButton) + buttonControl(NULL); } memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); _system->copyRectToScreen(_screenBuf, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); - _system->updateScreen(); + if (!SkyEngine::_systemVars.quitGame) + _system->updateScreen(); _skyScreen->forceRefresh(); _skyScreen->setPaletteEndian((uint8 *)_skyCompact->fetchCpt(SkyEngine::_systemVars.currentPalette)); removePanel(); @@ -583,11 +581,8 @@ uint16 Control::handleClick(ConResource *pButton) { return 0; case QUIT_TO_DOS: animClick(pButton); - if (getYesNo(quitDos)) { - showGameQuitMsg(false); - delay(1500); - _system->quit(); - } + if (getYesNo(quitDos)) + SkyEngine::_systemVars.quitGame = true; return 0; default: error("Control::handleClick: unknown routine: %X",pButton->_onClick); @@ -1538,8 +1533,7 @@ void Control::delay(unsigned int amount) { case OSystem::EVENT_RBUTTONDOWN: break; case OSystem::EVENT_QUIT: - if (!SkyEngine::_systemVars.quitting) - showGameQuitMsg(false); + SkyEngine::_systemVars.quitGame = true; break; default: break; @@ -1559,20 +1553,17 @@ void Control::delay(unsigned int amount) { } while (cur < start + amount); } -void Control::showGameQuitMsg(bool useScreen) { +void Control::showGameQuitMsg(void) { - SkyEngine::_systemVars.quitting = true; _skyText->fnSetFont(0); uint8 *textBuf1 = (uint8 *)malloc(GAME_SCREEN_WIDTH * 14 + sizeof(dataFileHeader)); uint8 *textBuf2 = (uint8 *)malloc(GAME_SCREEN_WIDTH * 14 + sizeof(dataFileHeader)); uint8 *screenData; - if (useScreen) { - if (_skyScreen->sequenceRunning()) - _skyScreen->stopSequence(); + if (_skyScreen->sequenceRunning()) + _skyScreen->stopSequence(); + + screenData = _skyScreen->giveCurrent(); - screenData = _skyScreen->giveCurrent(); - } else - screenData = _screenBuf; _skyText->displayText(_quitTexts[SkyEngine::_systemVars.language * 2 + 0], textBuf1, true, 320, 255); _skyText->displayText(_quitTexts[SkyEngine::_systemVars.language * 2 + 1], textBuf2, true, 320, 255); uint8 *curLine1 = textBuf1 + sizeof(dataFileHeader); @@ -1591,19 +1582,8 @@ void Control::showGameQuitMsg(bool useScreen) { } _skyScreen->halvePalette(); _skyScreen->showScreen(screenData); - free(textBuf1); free(textBuf2); - - // __tom (FIXME): This is a poor method of turning - // off music. ~GmMusic, ~AdlibMusic, and ~MT32Music - // should do it themselves so the appropriate MIDI - // controller events (e.g. 123/'All Notes Off') can - // be sent. However, that requires a re-write of - // other code and for now this fixes hanging notes - // on MT-32 + other external GMIDI synths. - _skyMusic->stopMusic(); - delay(1500); - ConfMan.flushToDisk(); - _system->quit(); + free(textBuf1); + free(textBuf2); } char Control::_quitTexts[16][35] = { diff --git a/sky/control.h b/sky/control.h index 903b713efe..c5cddc9c65 100644 --- a/sky/control.h +++ b/sky/control.h @@ -181,7 +181,7 @@ public: void doControlPanel(void); void doLoadSavePanel(void); void restartGame(void); - void showGameQuitMsg(bool useScreen = true); + void showGameQuitMsg(void); void doAutoSave(void); uint16 quickXRestore(uint16 slot); bool loadSaveAllowed(void); diff --git a/sky/disk.cpp b/sky/disk.cpp index 22091cc72b..ba5930a959 100644 --- a/sky/disk.cpp +++ b/sky/disk.cpp @@ -77,6 +77,8 @@ Disk::~Disk(void) { _dnrHandle->close(); if (_dataDiskHandle->isOpen()) _dataDiskHandle->close(); + fnFlushBuffers(); + free(_dinnerTableArea); delete _dnrHandle; delete _dataDiskHandle; } @@ -374,7 +376,7 @@ void Disk::fnFlushBuffers(void) { uint8 lCnt = 0; while (_loadedFilesList[lCnt]) { free(SkyEngine::_itemList[_loadedFilesList[lCnt] & 2047]); - SkyEngine::_itemList[_loadedFilesList[lCnt] & 2047] = 0; + SkyEngine::_itemList[_loadedFilesList[lCnt] & 2047] = NULL; lCnt++; } _loadedFilesList[0] = 0; diff --git a/sky/intro.cpp b/sky/intro.cpp index dfaf2db00f..f271545933 100644 --- a/sky/intro.cpp +++ b/sky/intro.cpp @@ -827,8 +827,7 @@ bool Intro::commandFlirt(uint16 *&data) { uint16 command = *data++; switch(command) { case IC_PREPARE_TEXT: - _skyText->getText(*data++); - _skyText->displayText(_textBuf, true, INTRO_TEXT_WIDTH, 255); + _skyText->displayText(*data++, _textBuf, true, INTRO_TEXT_WIDTH, 255); break; case IC_SHOW_TEXT: ((dataFileHeader*)_textBuf)->s_x = *data++; diff --git a/sky/logic.cpp b/sky/logic.cpp index 00f7ace25b..3402fb36ad 100644 --- a/sky/logic.cpp +++ b/sky/logic.cpp @@ -87,6 +87,11 @@ Logic::Logic(SkyCompact *skyCompact, Screen *skyScreen, Disk *skyDisk, Text *sky initScriptVariables(); } +Logic::~Logic(void) { + delete _skyGrid; + delete _skyAutoRoute; +} + void Logic::initScreen0(void) { fnEnterSection(0, 0, 0); _skyMusic->startMusic(2); @@ -2464,8 +2469,8 @@ bool Logic::fnFadeUp(uint32 a, uint32 b, uint32 c) { } bool Logic::fnQuitToDos(uint32 a, uint32 b, uint32 c) { - _skyControl->showGameQuitMsg(); // calls _system->quit() - return true; + SkyEngine::_systemVars.quitGame = true; + return false; } bool Logic::fnPauseFx(uint32 a, uint32 b, uint32 c) { @@ -2561,7 +2566,7 @@ void Logic::stdSpeak(Compact *target, uint32 textNum, uint32 animNum, uint32 bas if (speechUsed) target->spTime = 10; else - target->spTime = (uint16)_skyText->_dtLetters + 5; + target->spTime = (uint16)_skyText->_numLetters + 5; target->logic = L_TALK; } diff --git a/sky/logic.h b/sky/logic.h index d00abbe43e..9ceb93532f 100644 --- a/sky/logic.h +++ b/sky/logic.h @@ -140,6 +140,7 @@ public: MusicBase *skyMusic, Mouse *skyMouse, Sound *skySound); + ~Logic(void); void engine(); void useControlInstance(Control *control) { _skyControl = control; }; diff --git a/sky/music/adlibchannel.cpp b/sky/music/adlibchannel.cpp index c0cba9508f..7705f66e70 100644 --- a/sky/music/adlibchannel.cpp +++ b/sky/music/adlibchannel.cpp @@ -84,7 +84,7 @@ bool AdlibChannel::isActive(void) { void AdlibChannel::updateVolume(uint16 pVolume) { - _musicVolume = pVolume; + _musicVolume = pVolume * 3; } /* This class uses the same area for the register mirror as the original diff --git a/sky/music/adlibmusic.cpp b/sky/music/adlibmusic.cpp index c308791f22..cfa608c4e6 100644 --- a/sky/music/adlibmusic.cpp +++ b/sky/music/adlibmusic.cpp @@ -41,14 +41,6 @@ AdlibMusic::AdlibMusic(Audio::Mixer *pMixer, Disk *pDisk) AdlibMusic::~AdlibMusic(void) { _mixer->setupPremix(0); -// YM3812Shutdown(); -} - -void AdlibMusic::setVolume(uint8 volume) { - - _musicVolume = volume; - for (uint8 cnt = 0; cnt < _numberOfChannels; cnt++) - _channels[cnt]->updateVolume(volume | 128); } void AdlibMusic::premixerCall(int16 *data, uint len) { @@ -111,7 +103,7 @@ void AdlibMusic::setupChannels(uint8 *channelData) { for (uint8 cnt = 0; cnt < _numberOfChannels; cnt++) { uint16 chDataStart = ((channelData[(cnt << 1) | 1] << 8) | channelData[cnt << 1]) + _musicDataLoc; _channels[cnt] = new AdlibChannel(_opl, _musicData, chDataStart); - _channels[cnt]->updateVolume(_musicVolume | 128); + _channels[cnt]->updateVolume(_musicVolume); } } diff --git a/sky/music/adlibmusic.h b/sky/music/adlibmusic.h index db6685b3d0..307e5e7e35 100644 --- a/sky/music/adlibmusic.h +++ b/sky/music/adlibmusic.h @@ -36,7 +36,6 @@ class AdlibMusic : public AudioStream, public MusicBase { public: AdlibMusic(Audio::Mixer *pMixer, Disk *pDisk); ~AdlibMusic(void); - virtual void setVolume(uint8 volume); // AudioStream API int readBuffer(int16 *buffer, const int numSamples) { diff --git a/sky/music/gmmusic.cpp b/sky/music/gmmusic.cpp index 56a25728df..94b1247300 100644 --- a/sky/music/gmmusic.cpp +++ b/sky/music/gmmusic.cpp @@ -58,11 +58,6 @@ GmMusic::~GmMusic(void) { delete _midiDrv; } -void GmMusic::setVolume(uint8 volume) { - - setFMVolume(volume); -} - void GmMusic::timerCall(void) { _timerCount += _midiDrv->getBaseTempo(); if (_timerCount > (1000000 / 50)) { diff --git a/sky/music/gmmusic.h b/sky/music/gmmusic.h index 3d23141ac0..9acd1f135f 100644 --- a/sky/music/gmmusic.h +++ b/sky/music/gmmusic.h @@ -32,7 +32,6 @@ class GmMusic : public MusicBase { public: GmMusic(MidiDriver *pMidiDrv, Disk *pDisk); ~GmMusic(void); - virtual void setVolume(uint8 volume); private: static void passTimerFunc(void *param); void timerCall(void); diff --git a/sky/music/musicbase.cpp b/sky/music/musicbase.cpp index 209a46d263..66995d674a 100644 --- a/sky/music/musicbase.cpp +++ b/sky/music/musicbase.cpp @@ -37,6 +37,7 @@ MusicBase::MusicBase(Disk *pDisk) { MusicBase::~MusicBase(void) { + stopMusic(); if (_musicData) free(_musicData); } @@ -71,47 +72,7 @@ bool MusicBase::musicIsPlaying(void) { return false; } -void MusicBase::musicCommand(uint16 command) { - - if (_musicData == NULL) { - debug(1,"Got music command but driver is not yet loaded"); - return ; - } - if ((command >> 8) > _allowedCommands) { - debug(1,"got musicCommand %d while expecting <= %d", command >> 8, _allowedCommands); - return ; - } - switch(command >> 8) { - case 0: - debug(1,"Music: got call to startAdlibDriver(). Not necessary in this implementation."); - break; - case 1: - debug(1,"Music: got call to stopDriver(). Not necessary in this implementation."); - break; - case 2: - debug(1,"Music: got call to SetTempo(). Tempo is fixed in this implementation."); - break; - case 3: - debug(1,"Music: ignored direct call to driverPoll()."); - break; - case 4: - startMusic(command & 0xFF); - break; - case 6: - reinitFM(); - break; - case 7: - stopMusic(); - break; - case 13: - setFMVolume(command & 0xFF); - break; - default: - debug(1,"musicCommand %d ignored.",command >> 8); - } -} - -void MusicBase::setFMVolume(uint16 param) { +void MusicBase::setVolume(uint16 param) { _musicVolume = param; for (uint8 cnt = 0; cnt < _numberOfChannels; cnt++) diff --git a/sky/music/musicbase.h b/sky/music/musicbase.h index 9a73844bc0..bf5f8e326b 100644 --- a/sky/music/musicbase.h +++ b/sky/music/musicbase.h @@ -52,13 +52,12 @@ public: MusicBase(Disk *pDisk); virtual ~MusicBase(void); void loadSection(uint8 pSection); - void musicCommand(uint16 command); void startMusic(uint16 param) { _onNextPoll.musicToProcess = param & 0xF; }; // 4 void stopMusic(); // 7 bool musicIsPlaying(void); - virtual void setVolume(uint8 volume) = 0; uint8 giveVolume(void) { return (uint8)_musicVolume; }; uint8 giveCurrentMusic(void) { return _currentMusic; }; + void setVolume(uint16 param); protected: @@ -80,16 +79,11 @@ protected: virtual void setupPointers(void) = 0; virtual void setupChannels(uint8 *channelData) = 0; + virtual void startDriver(void) = 0; void updateTempo(void); void loadNewMusic(void); - //- functions from CommandTable @0x90 (the main interface) - virtual void startDriver(void) = 0; // 0 - void StopDriver(void); // 1 - void setTempo(uint16 newTempo); // 2 - void pollMusic(); // 3 - void reinitFM(void) { _onNextPoll.doReInit = true; }; // 6 - void setFMVolume(uint16 param); // 13 + void pollMusic(void); }; } // End of namespace Sky diff --git a/sky/sky.cpp b/sky/sky.cpp index 6cba9981af..2534841045 100644 --- a/sky/sky.cpp +++ b/sky/sky.cpp @@ -123,6 +123,8 @@ SkyEngine::SkyEngine(GameDetector *detector, OSystem *syst) SkyEngine::~SkyEngine() { + _timer->removeTimerProc(&timerHandler); + delete _skyLogic; delete _skySound; delete _skyMusic; @@ -130,6 +132,11 @@ SkyEngine::~SkyEngine() { delete _skyMouse; delete _skyScreen; delete _debugger; + delete _skyDisk; + + for (int i = 0; i < 300; i++) + if (_itemList[i]) + free(_itemList[i]); } void SkyEngine::errorString(const char *buf1, char *buf2) { @@ -206,6 +213,8 @@ void SkyEngine::handleKey(void) { int SkyEngine::go() { + _systemVars.quitGame = false; + _mouseX = GAME_SCREEN_WIDTH / 2; _mouseY = GAME_SCREEN_HEIGHT / 2; _keyFlags = _keyPressed = 0; @@ -216,25 +225,24 @@ int SkyEngine::go() { if (result != GAME_RESTORED) { bool introSkipped = false; - if (_systemVars.gameVersion > 267) {// don't do intro for floppydemos + if (_systemVars.gameVersion > 267) { // don't do intro for floppydemos _skyIntro = new Intro(_skyDisk, _skyScreen, _skyMusic, _skySound, _skyText, _mixer, _system); introSkipped = !_skyIntro->doIntro(_floppyIntro); - if (_skyIntro->_quitProg) { - delete _skyIntro; - _skyControl->showGameQuitMsg(); - } + _systemVars.quitGame = _skyIntro->_quitProg; + delete _skyIntro; } - _skyLogic->initScreen0(); - - if (introSkipped) - _skyControl->restartGame(); + if (!_systemVars.quitGame) { + _skyLogic->initScreen0(); + if (introSkipped) + _skyControl->restartGame(); + } } _lastSaveTime = _system->getMillis(); - while (1) { + while (!_systemVars.quitGame) { if (_debugger->isAttached()) _debugger->onFrame(); @@ -273,6 +281,10 @@ int SkyEngine::go() { delay((frameTime + _systemVars.gameSpeed) - _system->getMillis()); } + _skyControl->showGameQuitMsg(); + _skyMusic->stopMusic(); + ConfMan.flushToDisk(); + delay(1500); return 0; } @@ -372,12 +384,12 @@ int SkyEngine::init(GameDetector &detector) { if (!_skyDisk->fileExists(60600 + SkyEngine::_systemVars.language * 8)) { warning("The language you selected does not exist in your BASS version."); if (_skyDisk->fileExists(60600)) - SkyEngine::_systemVars.language = SKY_ENGLISH; + SkyEngine::_systemVars.language = SKY_ENGLISH; // default to GB english if it exists.. else if (_skyDisk->fileExists(60600 + SKY_USA * 8)) - SkyEngine::_systemVars.language = SKY_USA; + SkyEngine::_systemVars.language = SKY_USA; // try US english... else for (uint8 cnt = SKY_ENGLISH; cnt <= SKY_SPANISH; cnt++) - if (_skyDisk->fileExists(60600 + cnt * 8)) { + if (_skyDisk->fileExists(60600 + cnt * 8)) { // pick the first language we can find SkyEngine::_systemVars.language = cnt; break; } @@ -395,22 +407,6 @@ void SkyEngine::initItemList() { for (int i = 0; i < 300; i++) _itemList[i] = NULL; - - //init the non-null items - // I don't see where the script could possible access this.. so it should be safe to - // leave these as NULL. - /*_itemList[119] = (void **)SkyCompact::data_0; // Compacts - Section 0 - _itemList[120] = (void **)SkyCompact::data_1; // Compacts - Section 1 - - if (isDemo()) { - _itemList[121] = _itemList[122] = _itemList[123] = _itemList[124] = _itemList[125] = (void **)SkyCompact::data_0; - } else { - _itemList[121] = (void **)SkyCompact::data_2; // Compacts - Section 2 - _itemList[122] = (void **)SkyCompact::data_3; // Compacts - Section 3 - _itemList[123] = (void **)SkyCompact::data_4; // Compacts - Section 4 - _itemList[124] = (void **)SkyCompact::data_5; // Compacts - Section 5 - _itemList[125] = (void **)SkyCompact::data_6; // Compacts - Section 6 - }*/ } void SkyEngine::loadFixedItems(void) { @@ -486,8 +482,7 @@ void SkyEngine::delay(int32 amount) { _skyMouse->buttonPressed(1); break; case OSystem::EVENT_QUIT: - if (!SkyEngine::_systemVars.quitting) - _skyControl->showGameQuitMsg(); // will call _system->quit() + _systemVars.quitGame = true; break; default: break; @@ -38,7 +38,7 @@ struct SystemVars { uint16 gameSpeed; uint16 currentMusic; bool pastIntro; - bool quitting; + bool quitGame; bool paused; }; diff --git a/sky/skydefs.h b/sky/skydefs.h index e0c3f78928..92683ba786 100644 --- a/sky/skydefs.h +++ b/sky/skydefs.h @@ -57,6 +57,7 @@ namespace Sky { #define SEQUENCE_COUNT 3 #define FIRST_TEXT_COMPACT 23 +#define LAST_TEXT_COMPACT 33 #define FIXED_TEXT_WIDTH 128 //screen/grid defines diff --git a/sky/sound.cpp b/sky/sound.cpp index 3ed3006190..98f1f4259e 100644 --- a/sky/sound.cpp +++ b/sky/sound.cpp @@ -1028,7 +1028,8 @@ Sound::Sound(Audio::Mixer *mixer, Disk *pDisk, uint8 pVolume) { Sound::~Sound(void) { _mixer->stopAll(); - if (_soundData) free(_soundData); + if (_soundData) + free(_soundData); } void Sound::playSound(uint32 id, byte *sound, uint32 size, Audio::SoundHandle *handle) { @@ -1048,7 +1049,8 @@ void Sound::loadSection(uint8 pSection) { fnStopFx(); _mixer->stopAll(); - if (_soundData) free(_soundData); + if (_soundData) + free(_soundData); _soundData = _skyDisk->loadFile(pSection * 4 + SOUND_FILE_BASE); uint16 asmOfs; if (SkyEngine::_systemVars.gameVersion == 109) { @@ -1065,10 +1067,8 @@ void Sound::loadSection(uint8 pSection) { error("Unknown sounddriver version!"); _soundsTotal = _soundData[asmOfs + 1]; - uint16 sRateTabOfs = (_soundData[asmOfs + 0x2A] << 8) | _soundData[asmOfs + 0x29]; - _sfxBaseOfs = (_soundData[asmOfs + 0x32] << 8) | _soundData[asmOfs + 0x31]; + _sfxBaseOfs = READ_LE_UINT16(_soundData + asmOfs + 0x31); - _sampleRates = _soundData + sRateTabOfs; _sfxInfo = _soundData + _sfxBaseOfs; // if we just restored a savegame, the sfxqueue holds the sound we need to restart if (!(SkyEngine::_systemVars.systemFlags & SF_GAME_RESTORED)) @@ -1093,20 +1093,15 @@ void Sound::playSound(uint16 sound, uint16 volume, uint8 channel) { return; } - volume = ((volume & 0x7F) + 1) << 1; - if (volume > 255) - volume = 255; + volume = (volume & 0x7F) << 1; sound &= 0xFF; // note: all those tables are big endian. Don't ask me why. *sigh* - uint16 sampleRate = (_sampleRates[sound << 2] << 8) | _sampleRates[(sound << 2) | 1]; - if (sampleRate > 11025) - sampleRate = 11025; - uint32 dataOfs = ((_sfxInfo[sound << 3] << 8) | _sfxInfo[(sound << 3) | 1]) << 4; + uint32 dataOfs = READ_BE_UINT16(_sfxInfo + (sound << 3) + 0) << 4; + uint32 dataSize = READ_BE_UINT16(_sfxInfo + (sound << 3) + 2); + uint32 dataLoop = READ_BE_UINT16(_sfxInfo + (sound << 3) + 6); dataOfs += _sfxBaseOfs; - uint16 dataSize = (_sfxInfo[(sound << 3) | 2] << 8) | _sfxInfo[(sound << 3) | 3]; - uint16 dataLoop = (_sfxInfo[(sound << 3) | 6] << 8) | _sfxInfo[(sound << 3) | 7]; - + byte flags = Audio::Mixer::FLAG_UNSIGNED; uint32 loopSta = 0, loopEnd = 0; @@ -1117,9 +1112,9 @@ void Sound::playSound(uint16 sound, uint16 volume, uint8 channel) { } if (channel == 0) - _mixer->playRaw(&_ingameSound0, _soundData + dataOfs, dataSize, sampleRate, flags, SOUND_CH0, volume, 0, loopSta, loopEnd); + _mixer->playRaw(&_ingameSound0, _soundData + dataOfs, dataSize, 11025, flags, SOUND_CH0, volume, 0, loopSta, loopEnd); else - _mixer->playRaw(&_ingameSound1, _soundData + dataOfs, dataSize, sampleRate, flags, SOUND_CH1, volume, 0, loopSta, loopEnd); + _mixer->playRaw(&_ingameSound1, _soundData + dataOfs, dataSize, 11025, flags, SOUND_CH1, volume, 0, loopSta, loopEnd); } void Sound::fnStartFx(uint32 sound, uint8 channel) { diff --git a/sky/sound.h b/sky/sound.h index 03c1d03cc3..fe1be9b828 100644 --- a/sky/sound.h +++ b/sky/sound.h @@ -82,7 +82,7 @@ private: Disk *_skyDisk; uint16 _sfxBaseOfs; uint8 *_soundData; - uint8 *_sampleRates, *_sfxInfo; + uint8 *_sfxInfo; uint8 _mainSfxVolume; static uint16 _speechConvertTable[8]; diff --git a/sky/struc.h b/sky/struc.h index c42d1ca978..1dfa93129c 100644 --- a/sky/struc.h +++ b/sky/struc.h @@ -26,6 +26,7 @@ namespace Sky { struct lowTextManager_t { byte *textData; + uint32 textWidth; uint16 compactNum; }; diff --git a/sky/text.cpp b/sky/text.cpp index e55f4b6ef5..82cdbca7f9 100644 --- a/sky/text.cpp +++ b/sky/text.cpp @@ -31,6 +31,7 @@ namespace Sky { #define FIRST_TEXT_SEC 77 #define FIRST_TEXT_BUFFER 274 +#define LAST_TEXT_BUFFER 284 #define NO_OF_TEXT_SECTIONS 8 // 8 sections per language #define CHAR_SET_FILE 60150 #define MAX_SPEECH_SECTION 7 @@ -63,18 +64,21 @@ Text::Text(Disk *skyDisk, SkyCompact *skyCompact) { _controlCharacterSet.addr = NULL; _linkCharacterSet.addr = NULL; } - - if (SkyEngine::isCDVersion()) { - _preAfterTableArea = _skyDisk->loadFile(60522); - } else - _preAfterTableArea = NULL; } Text::~Text(void) { + for (int i = FIRST_TEXT_BUFFER; i <= LAST_TEXT_BUFFER; i++) + if (SkyEngine::_itemList[i]) { + free(SkyEngine::_itemList[i]); + SkyEngine::_itemList[i] = NULL; + } - if (_controlCharacterSet.addr) free(_controlCharacterSet.addr); - if (_linkCharacterSet.addr) free(_linkCharacterSet.addr); - if (_preAfterTableArea) free(_preAfterTableArea); + if (_mainCharacterSet.addr) + free(_mainCharacterSet.addr); + if (_controlCharacterSet.addr) + free(_controlCharacterSet.addr); + if (_linkCharacterSet.addr) + free(_linkCharacterSet.addr); } void Text::patchChar(byte *charSetPtr, int width, int height, int c, const uint16 *data) { @@ -97,9 +101,9 @@ void Text::patchLINCCharset() { byte *charSetPtr = _controlCharacterSet.addr; int charHeight = _controlCharacterSet.charHeight; - // In v0.0288, decrease the character spacing is too wide. Decrease - // the width for every character by one, except for space which needs - // to be one pixel wider than before. + // In v0.0288, the character spacing is too wide. Decrease the width + // for every character by one, except for space which needs to be one + // pixel wider than before. if (SkyEngine::_systemVars.gameVersion == 288) { for (int i = 1; i < CHAR_SET_HEADER; i++) @@ -247,8 +251,6 @@ void Text::patchLINCCharset() { patchChar(charSetPtr, 5, charHeight, 74, normal_j); patchChar(charSetPtr, 6, charHeight, 17, normal_1); - // TODO: Verify that these work in all versions - patchChar(charSetPtr, 5, charHeight, 11, e_acute); patchChar(charSetPtr, 5, charHeight, 61, e_grave); patchChar(charSetPtr, 5, charHeight, 29, e_circumflex); @@ -311,68 +313,57 @@ void Text::getText(uint32 textNr) { //load text #"textNr" into textBuffer uint32 sectionNo = (textNr & 0x0F000) >> 12; - if (SkyEngine::_itemList[FIRST_TEXT_SEC + sectionNo] == (void **)NULL) { //check if already loaded + if (SkyEngine::_itemList[FIRST_TEXT_SEC + sectionNo] == NULL) { //check if already loaded debug(5, "Loading Text item(s) for Section %d", (sectionNo >> 2)); uint32 fileNo = sectionNo + ((SkyEngine::_systemVars.language * NO_OF_TEXT_SECTIONS) + 60600); SkyEngine::_itemList[FIRST_TEXT_SEC + sectionNo] = (void **)_skyDisk->loadFile((uint16)fileNo); } - _textItemPtr = (uint8 *)SkyEngine::_itemList[FIRST_TEXT_SEC + sectionNo]; + uint8 *textDataPtr = (uint8 *)SkyEngine::_itemList[FIRST_TEXT_SEC + sectionNo]; uint32 offset = 0; - uint32 nr32MsgBlocks = (textNr & 0x0fe0); - uint32 skipBytes; - byte *blockPtr; - bool bitSeven; - - if (nr32MsgBlocks) { - blockPtr = (byte *)(_textItemPtr + 4); - nr32MsgBlocks >>= 5; + + uint32 blockNr = textNr & 0xFE0; + textNr &= 0x1F; + + if (blockNr) { + uint16 *blockPtr = (uint16*)(textDataPtr + 4); + uint32 nr32MsgBlocks = blockNr >> 5; + do { offset += READ_LE_UINT16(blockPtr); - blockPtr += 2; + blockPtr++; } while (--nr32MsgBlocks); } - uint32 remItems = textNr; - textNr &= 0x1f; if (textNr) { - - remItems &= 0x0fe0; - remItems += READ_LE_UINT16(_textItemPtr); - blockPtr = _textItemPtr + remItems; - + uint8 *blockPtr = textDataPtr + blockNr + READ_LE_UINT16(textDataPtr); do { - skipBytes = *blockPtr++; - bitSeven = (bool)((skipBytes >> (7)) & 0x1); - skipBytes &= ~(1UL << 7); - - if (bitSeven) + uint8 skipBytes = *blockPtr++; + if (skipBytes & 0x80) { + skipBytes &= 0x7F; skipBytes <<= 3; - + } offset += skipBytes; - } while (--textNr); } - uint32 numBits = offset; + uint32 bitPos = offset & 3; offset >>= 2; - offset += READ_LE_UINT16(_textItemPtr + 2); - _textItemPtr += offset; + offset += READ_LE_UINT16(textDataPtr + 2); + + textDataPtr += offset; //bit pointer: 0->8, 1->6, 2->4 ... - numBits &= 3; - numBits ^= 3; - numBits++; - numBits <<= 1; + bitPos ^= 3; + bitPos++; + bitPos <<= 1; - _inputValue = *_textItemPtr++; char *dest = (char *)_textBuffer; char textChar; - _shiftBits = (uint8) numBits; do { - textChar = getTextChar(); + textChar = getTextChar(&textDataPtr, &bitPos); *dest++ = textChar; } while (textChar); } @@ -384,12 +375,16 @@ void Text::fnPointerText(uint32 pointedId, uint16 mouseX, uint16 mouseY) { Logic::_scriptVariables[CURSOR_ID] = text.compactNum; if (Logic::_scriptVariables[MENU]) { _mouseOfsY = TOP_LEFT_Y - 2; - if (mouseX < 150) _mouseOfsX = TOP_LEFT_X + 24; - else _mouseOfsX = TOP_LEFT_X - 8 - _lowTextWidth; + if (mouseX < 150) + _mouseOfsX = TOP_LEFT_X + 24; + else + _mouseOfsX = TOP_LEFT_X - 8 - text.textWidth; } else { _mouseOfsY = TOP_LEFT_Y - 10; - if (mouseX < 150) _mouseOfsX = TOP_LEFT_X + 13; - else _mouseOfsX = TOP_LEFT_X - 8 - _lowTextWidth; + if (mouseX < 150) + _mouseOfsX = TOP_LEFT_X + 13; + else + _mouseOfsX = TOP_LEFT_X - 8 - text.textWidth; } Compact *textCompact = _skyCompact->fetchCpt(text.compactNum); logicCursor(textCompact, mouseX, mouseY); @@ -399,46 +394,50 @@ void Text::logicCursor(Compact *textCompact, uint16 mouseX, uint16 mouseY) { textCompact->xcood = (uint16)(mouseX + _mouseOfsX); textCompact->ycood = (uint16)(mouseY + _mouseOfsY); - if (textCompact->ycood < TOP_LEFT_Y) textCompact->ycood = TOP_LEFT_Y; + if (textCompact->ycood < TOP_LEFT_Y) + textCompact->ycood = TOP_LEFT_Y; } -bool Text::getTBit() { +bool Text::getTextBit(uint8 **data, uint32 *bitPos) { - if (_shiftBits) { - (_shiftBits)--; + if (*bitPos) { + (*bitPos)--; } else { - _inputValue = *_textItemPtr++; - _shiftBits = 7; + (*data)++; + *bitPos = 7; } - return (bool)(((_inputValue) >> (_shiftBits)) & 1); + return (bool)(((**data) >> (*bitPos)) & 1); } -displayText_t Text::displayText(uint8 *dest, bool centre, uint16 pixelWidth, uint8 color) { - //Render text in _textBuffer in buffer *dest - return displayText(this->_textBuffer, dest, centre, pixelWidth, color); +char Text::getTextChar(uint8 **data, uint32 *bitPos) { + int pos = 0; + while (1) { + if (getTextBit(data, bitPos)) + pos = _huffTree[pos].rChild; + else + pos = _huffTree[pos].lChild; + + if (_huffTree[pos].lChild == 0 && _huffTree[pos].rChild == 0) { + return _huffTree[pos].value; + } + } +} + +displayText_t Text::displayText(uint32 textNum, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color) { + //Render text into buffer *dest + getText(textNum); + return displayText(_textBuffer, dest, centre, pixelWidth, color); } displayText_t Text::displayText(char *textPtr, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color) { //Render text pointed to by *textPtr in buffer *dest - - uint8 textChar; - char *curPos = textPtr; - char *lastSpace = curPos; - byte *centerTblPtr = _centreTable; + uint32 centerTable[10]; uint16 lineWidth = 0; - _dtCol = color; - _dtLineWidth = pixelWidth; - _dtLines = 0; - _dtLetters = 1; - _dtData = dest; - _dtText = textPtr; - _dtCentre = centre; - - textChar = (uint8)*curPos++; - _dtLetters++; + uint32 numLines = 0; + _numLetters = 2; // work around bug #778105 (line width exceeded) char *tmpPtr = strstr(textPtr, "MUND-BEATMUNG!"); @@ -452,6 +451,10 @@ displayText_t Text::displayText(char *textPtr, uint8 *dest, bool centre, uint16 if (tmpPtr) strcpy(tmpPtr, "MANIFESTACION ARTISTICA."); + char *curPos = textPtr; + char *lastSpace = textPtr; + uint8 textChar = (uint8)*curPos++; + while (textChar >= 0x20) { if ((_curCharSet == 1) && (textChar >= 0x80)) textChar = 0x20; @@ -459,10 +462,10 @@ displayText_t Text::displayText(char *textPtr, uint8 *dest, bool centre, uint16 textChar -= 0x20; if (textChar == 0) { lastSpace = curPos; //keep track of last space - *(uint32 *)centerTblPtr = TO_LE_32(lineWidth); + centerTable[numLines] = lineWidth; } - lineWidth += *(_characterSet+textChar); //add character width + lineWidth += _characterSet[textChar]; //add character width lineWidth += (uint16)_dtCharSpacing; //include character spacing if (pixelWidth <= lineWidth) { @@ -472,74 +475,68 @@ displayText_t Text::displayText(char *textPtr, uint8 *dest, bool centre, uint16 *(lastSpace-1) = 10; lineWidth = 0; - _dtLines++; - centerTblPtr += 4; //get next space in centering table + numLines++; curPos = lastSpace; //go back for new count } textChar = (uint8)*curPos++; - _dtLetters++; + _numLetters++; } - _dtLastWidth = lineWidth; //save width of last line - *(uint32 *)centerTblPtr = TO_LE_32(lineWidth); //and update centering table - _dtLines++; + uint32 dtLastWidth = lineWidth; //save width of last line + centerTable[numLines] = lineWidth; //and update centering table + numLines++; - if (_dtLines > MAX_NO_LINES) + if (numLines > MAX_NO_LINES) error("Maximum no. of lines exceeded!"); - _dtLineSize = pixelWidth * _charHeight; - uint32 numBytes = (_dtLineSize * _dtLines) + sizeof(struct dataFileHeader) + 4; - - if (_dtData == NULL) - _dtData = (byte *)malloc(numBytes); + uint32 dtLineSize = pixelWidth * _charHeight; + uint32 numBytes = (dtLineSize * numLines) + sizeof(struct dataFileHeader) + 4; - uint8 *curDest = _dtData; + if (!dest) + dest = (uint8*)malloc(numBytes); - uint32 bytesToClear = numBytes; //no of bytes to clear - bytesToClear -= sizeof(struct dataFileHeader); //don't touch the header. - memset(curDest + sizeof(struct dataFileHeader), 0, bytesToClear); - curPos += bytesToClear; + // clear text sprite buffer + memset(dest + sizeof(struct dataFileHeader), 0, numBytes - sizeof(struct dataFileHeader)); //make the header - ((struct dataFileHeader *)curDest)->s_width = _dtLineWidth; - ((struct dataFileHeader *)curDest)->s_height = (uint16)(_charHeight * _dtLines); - ((struct dataFileHeader *)curDest)->s_sp_size = (uint16)(_dtLineWidth * _charHeight * _dtLines); - ((struct dataFileHeader *)curDest)->s_offset_x = 0; - ((struct dataFileHeader *)curDest)->s_offset_y = 0; + ((struct dataFileHeader *)dest)->s_width = pixelWidth; + ((struct dataFileHeader *)dest)->s_height = (uint16)(_charHeight * numLines); + ((struct dataFileHeader *)dest)->s_sp_size = (uint16)(pixelWidth * _charHeight * numLines); + ((struct dataFileHeader *)dest)->s_offset_x = 0; + ((struct dataFileHeader *)dest)->s_offset_y = 0; //reset position curPos = textPtr; - curDest += sizeof(struct dataFileHeader); //point to where pixels start + uint8 *curDest = dest + sizeof(struct dataFileHeader); //point to where pixels start byte *prevDest = curDest; - centerTblPtr = _centreTable; + uint32 *centerTblPtr = centerTable; do { - if (_dtCentre) { - - uint32 width = (_dtLineWidth - READ_LE_UINT32(centerTblPtr)) >> 1; - centerTblPtr += 4; + if (centre) { + uint32 width = (pixelWidth - *centerTblPtr) >> 1; + centerTblPtr++; curDest += width; } textChar = (uint8)*curPos++; while (textChar >= 0x20) { - makeGameCharacter(textChar - 0x20, _characterSet, curDest, color); + makeGameCharacter(textChar - 0x20, _characterSet, curDest, color, pixelWidth); textChar = *curPos++; } - prevDest = curDest = prevDest + _dtLineSize; //start of last line + start of next + prevDest = curDest = prevDest + dtLineSize; //start of last line + start of next } while (textChar >= 10); struct displayText_t ret; - ret.textData = _dtData; - ret.textWidth = _dtLastWidth; + ret.textData = dest; + ret.textWidth = dtLastWidth; return ret; } -void Text::makeGameCharacter(uint8 textChar, uint8 *charSetPtr, uint8 *&dest, uint8 color) { +void Text::makeGameCharacter(uint8 textChar, uint8 *charSetPtr, uint8 *&dest, uint8 color, uint16 bufPitch) { bool maskBit, dataBit; uint8 charWidth = (uint8)((*(charSetPtr + textChar)) + 1 - _dtCharSpacing); @@ -571,29 +568,20 @@ void Text::makeGameCharacter(uint8 textChar, uint8 *charSetPtr, uint8 *&dest, ui curPos++; } - //advance a line - curPos = prevPos + _dtLineWidth; + curPos = prevPos + bufPitch; } - //update position dest = startPos + charWidth + _dtCharSpacing * 2 - 1; - } lowTextManager_t Text::lowTextManager(uint32 textNum, uint16 width, uint16 logicNum, uint8 color, bool centre) { getText(textNum); - - struct displayText_t textInfo = displayText(NULL, centre, width, color); - - _lowTextWidth = textInfo.textWidth; - byte *textData = textInfo.textData; + struct displayText_t textInfo = displayText(_textBuffer, NULL, centre, width, color); uint32 compactNum = FIRST_TEXT_COMPACT; - Compact *cpt = _skyCompact->fetchCpt(compactNum); - while (cpt->status != 0) { compactNum++; cpt = _skyCompact->fetchCpt(compactNum); @@ -601,18 +589,18 @@ lowTextManager_t Text::lowTextManager(uint32 textNum, uint16 width, uint16 logic cpt->flag = (uint16)(compactNum - FIRST_TEXT_COMPACT) + FIRST_TEXT_BUFFER; - byte *oldText = (byte *)SkyEngine::_itemList[cpt->flag]; - SkyEngine::_itemList[cpt->flag] = (void **)textData; + if (SkyEngine::_itemList[cpt->flag]) + free(SkyEngine::_itemList[cpt->flag]); - if (oldText != NULL) - free (oldText); + SkyEngine::_itemList[cpt->flag] = textInfo.textData; cpt->logic = logicNum; cpt->status = ST_LOGIC | ST_FOREGROUND | ST_RECREATE; cpt->screen = (uint16) Logic::_scriptVariables[SCREEN]; struct lowTextManager_t ret; - ret.textData = _dtData; + ret.textData = textInfo.textData; + ret.textWidth = textInfo.textWidth; ret.compactNum = (uint16)compactNum; return ret; @@ -623,7 +611,12 @@ void Text::changeTextSpriteColour(uint8 *sprData, uint8 newCol) { dataFileHeader *header = (dataFileHeader *)sprData; sprData += sizeof(dataFileHeader); for (uint16 cnt = 0; cnt < header->s_sp_size; cnt++) - if (sprData[cnt] >= 241) sprData[cnt] = newCol; + if (sprData[cnt] >= 241) + sprData[cnt] = newCol; +} + +uint32 Text::giveCurrentCharSet(void) { + return _curCharSet; } void Text::initHuffTree() { @@ -660,19 +653,6 @@ void Text::initHuffTree() { } } -char Text::getTextChar() { - int pos = 0; - for (;;) { - if (getTBit() == 0) - pos = _huffTree[pos].lChild; - else - pos = _huffTree[pos].rChild; - if (_huffTree[pos].lChild == 0 && _huffTree[pos].rChild == 0) { - return _huffTree[pos].value; - } - } -} - bool Text::patchMessage(uint32 textNum) { uint16 patchIdx = _patchLangIdx[SkyEngine::_systemVars.language]; diff --git a/sky/text.h b/sky/text.h index 561d824f2f..9a864b9836 100644 --- a/sky/text.h +++ b/sky/text.h @@ -48,31 +48,31 @@ class Text { public: Text(Disk *skyDisk, SkyCompact *skyCompact); ~Text(void); - void getText(uint32 textNr); - struct displayText_t displayText(uint8 *dest, bool centre, uint16 pixelWidth, uint8 color); + struct displayText_t displayText(uint32 textNum, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color); struct displayText_t displayText(char *textPtr, uint8 *dest, bool centre, uint16 pixelWidth, uint8 color); - void makeGameCharacter(uint8 textChar, uint8 *charSetPtr, uint8 *&data, uint8 color); struct lowTextManager_t lowTextManager(uint32 textNum, uint16 width, uint16 logicNum, uint8 color, bool centre); void fnSetFont(uint32 fontNr); void fnTextModule(uint32 textInfoId, uint32 textNo); void fnPointerText(uint32 pointedId, uint16 mouseX, uint16 mouseY); void logicCursor(Compact *textCompact, uint16 mouseX, uint16 mouseY); void changeTextSpriteColour(uint8 *sprData, uint8 newCol); - uint32 giveCurrentCharSet(void) { return _curCharSet; }; + uint32 giveCurrentCharSet(void); + + uint32 _numLetters; //no of chars in message -protected: - bool getTBit(); +private: void initHuffTree(); - char getTextChar(); + void getText(uint32 textNr); + char getTextChar(uint8 **data, uint32 *bitPos); + bool getTextBit(uint8 **data, uint32 *bitPos); + void makeGameCharacter(uint8 textChar, uint8 *charSetPtr, uint8 *&data, uint8 color, uint16 bufPitch); + void patchChar(byte *charSetPtr, int width, int height, int c, const uint16 *data); void patchLINCCharset(); bool patchMessage(uint32 textNum); Disk *_skyDisk; SkyCompact *_skyCompact; - uint8 _inputValue; - uint8 _shiftBits; - uint8 *_textItemPtr; const HuffTree *_huffTree; @@ -85,23 +85,14 @@ protected: uint32 _curCharSet; uint8 *_characterSet; uint8 _charHeight; - uint8 *_preAfterTableArea; char _textBuffer[1024]; - uint8 _centreTable[40]; - - uint8 *_mouseTextData; //space for the mouse text - uint8 _dtCol; - uint16 _dtLineWidth; //width of line in pixels - uint32 _dtLines; //no of lines to do - uint32 _dtLineSize; //size of one line in bytes - uint8 *_dtData; //address of textdata - char *_dtText; //pointer to text + uint32 _dtCharSpacing; //character separation adjustment - uint32 _dtWidth; //width of chars in last line (for editing (?)) - uint32 _dtLastWidth; - bool _dtCentre; //set for centre text - uint32 _lowTextWidth, _mouseOfsX, _mouseOfsY; + uint32 _mouseOfsX, _mouseOfsY; + static const PatchMessage _patchedMessages[NUM_PATCH_MSG]; + static const uint16 _patchLangIdx[8]; + static const uint16 _patchLangNum[8]; #ifndef PALMOS_68K static const HuffTree _huffTree_00109[]; // trees moved to hufftext.cpp @@ -124,15 +115,7 @@ public: static const HuffTree *_huffTree_00365; static const HuffTree *_huffTree_00368; static const HuffTree *_huffTree_00372; -protected: #endif - - static const PatchMessage _patchedMessages[NUM_PATCH_MSG]; - static const uint16 _patchLangIdx[8]; - static const uint16 _patchLangNum[8]; - -public: - uint32 _dtLetters; //no of chars in message }; } // End of namespace Sky |