diff options
Diffstat (limited to 'engines/queen/journal.cpp')
-rw-r--r-- | engines/queen/journal.cpp | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/engines/queen/journal.cpp b/engines/queen/journal.cpp new file mode 100644 index 0000000000..0aeb71e083 --- /dev/null +++ b/engines/queen/journal.cpp @@ -0,0 +1,587 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2003-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/system.h" +#include "queen/journal.h" + +#include "queen/bankman.h" +#include "queen/display.h" +#include "queen/graphics.h" +#include "queen/grid.h" +#include "queen/logic.h" +#include "queen/music.h" +#include "queen/queen.h" +#include "queen/resource.h" +#include "queen/sound.h" + +namespace Queen { + +Journal::Journal(QueenEngine *vm) + : _vm(vm) { + _currentSavePage = 0; + _currentSaveSlot = 0; +} + +void Journal::use() { + BobSlot *joe = _vm->graphics()->bob(0); + _prevJoeX = joe->x; + _prevJoeY = joe->y; + + _panelMode = PM_NORMAL; + _system = &OSystem::instance(); + + _panelTextCount = 0; + memset(_panelTextY, 0, sizeof(_panelTextY)); + memset(&_textField, 0, sizeof(_textField)); + + memset(_saveDescriptions, 0, sizeof(_saveDescriptions)); + _vm->findGameStateDescriptions(_saveDescriptions); + + setup(); + redraw(); + update(); + _vm->display()->palFadeIn(ROOM_JOURNAL); + + _quitMode = QM_LOOP; + while (_quitMode == QM_LOOP) { + OSystem::Event event; + while (_system->pollEvent(event)) { + switch (event.type) { + case OSystem::EVENT_KEYDOWN: + handleKeyDown(event.kbd.ascii, event.kbd.keycode); + break; + case OSystem::EVENT_LBUTTONDOWN: + handleMouseDown(event.mouse.x, event.mouse.y); + break; + case OSystem::EVENT_WHEELUP: + handleMouseWheel(-1); + break; + case OSystem::EVENT_WHEELDOWN: + handleMouseWheel(1); + break; + case OSystem::EVENT_QUIT: + _system->quit(); + break; + default: + break; + } + } + _system->delayMillis(20); + _system->updateScreen(); + } + + _vm->writeOptionSettings(); + + _vm->display()->clearTexts(0, GAME_SCREEN_HEIGHT - 1); + _vm->graphics()->putCameraOnBob(0); + if (_quitMode == QM_CONTINUE) { + continueGame(); + } +} + +void Journal::continueGame() { + _vm->display()->fullscreen(false); + _vm->display()->forceFullRefresh(); + + _vm->logic()->joePos(_prevJoeX, _prevJoeY); + _vm->logic()->joeCutFacing(_vm->logic()->joeFacing()); + + _vm->logic()->oldRoom(_vm->logic()->currentRoom()); + _vm->logic()->displayRoom(_vm->logic()->currentRoom(), RDM_FADE_JOE, 0, 0, false); +} + +void Journal::setup() { + _vm->display()->palFadeOut(_vm->logic()->currentRoom()); + _vm->display()->horizontalScroll(0); + _vm->display()->fullscreen(true); + _vm->graphics()->clearBobs(); + _vm->display()->clearTexts(0, GAME_SCREEN_HEIGHT - 1); + _vm->bankMan()->eraseFrames(false); + _vm->display()->textCurrentColor(INK_JOURNAL); + + _vm->grid()->clear(GS_ROOM); + for (int i = 0; i < MAX_ZONES; ++i) { + const Zone *zn = &_zones[i]; + _vm->grid()->setZone(GS_ROOM, zn->num, zn->x1, zn->y1, zn->x2, zn->y2); + } + + _vm->display()->setupNewRoom("journal", ROOM_JOURNAL); + _vm->bankMan()->load("journal.BBK", JOURNAL_BANK); + for (int f = 1; f <= 20; ++f) { + int frameNum = JOURNAL_FRAMES + f; + _vm->bankMan()->unpack(f, frameNum, JOURNAL_BANK); + BobFrame *bf = _vm->bankMan()->fetchFrame(frameNum); + bf->xhotspot = 0; + bf->yhotspot = 0; + if (f == FRAME_INFO_BOX) { // adjust info box hot spot to put it always on top + bf->yhotspot = 200; + } + } + _vm->bankMan()->close(JOURNAL_BANK); + + _textField.x = 136; + _textField.y = 9; + _textField.w = 146; + _textField.h = 13; +} + +void Journal::redraw() { + drawNormalPanel(); + drawConfigPanel(); + drawSaveDescriptions(); + drawSaveSlot(); +} + +void Journal::update() { + _vm->graphics()->sortBobs(); + _vm->display()->prepareUpdate(); + _vm->graphics()->drawBobs(); + if (_textField.enabled) { + int16 x = _textField.x + _textField.posCursor; + int16 y = _textField.y + _currentSaveSlot * _textField.h + 8; + _vm->display()->drawBox(x, y, x + 6, y, INK_JOURNAL); + } + _vm->display()->forceFullRefresh(); + _vm->display()->update(); + _system->updateScreen(); +} + +void Journal::showBob(int bobNum, int16 x, int16 y, int frameNum) { + BobSlot *bob = _vm->graphics()->bob(bobNum); + bob->curPos(x, y); + bob->frameNum = JOURNAL_FRAMES + frameNum; +} + +void Journal::hideBob(int bobNum) { + _vm->graphics()->bob(bobNum)->active = false; +} + +void Journal::drawSaveDescriptions() { + for (int i = 0; i < NUM_SAVES_PER_PAGE; ++i) { + int n = _currentSavePage * 10 + i; + char nb[4]; + sprintf(nb, "%d", n + 1); + int y = _textField.y + i * _textField.h; + _vm->display()->setText(_textField.x, y, _saveDescriptions[n], false); + _vm->display()->setText(_textField.x - 27, y + 1, nb, false); + } + // highlight current page + showBob(BOB_SAVE_PAGE, 300, 3 + _currentSavePage * 15, 6 + _currentSavePage); +} + +void Journal::drawSaveSlot() { + showBob(BOB_SAVE_DESC, 130, 6 + _currentSaveSlot * 13, 17); +} + +void Journal::enterYesNoPanelMode(int16 prevZoneNum, int titleNum) { + _panelMode = PM_YES_NO; + _prevZoneNum = prevZoneNum; + drawYesNoPanel(titleNum); +} + +void Journal::exitYesNoPanelMode() { + _panelMode = PM_NORMAL; + if (_prevZoneNum == ZN_MAKE_ENTRY) { + closeTextField(); + } + redraw(); +} + +void Journal::enterInfoPanelMode() { + _panelMode = PM_INFO_BOX; + _vm->display()->clearTexts(0, GAME_SCREEN_HEIGHT - 1); + drawInfoPanel(); +} + +void Journal::exitInfoPanelMode() { + _vm->display()->clearTexts(0, GAME_SCREEN_HEIGHT - 1); + hideBob(BOB_INFO_BOX); + redraw(); + _panelMode = PM_NORMAL; +} + +void Journal::handleKeyDown(uint16 ascii, int keycode) { + switch (_panelMode) { + case PM_INFO_BOX: + break; + case PM_YES_NO: + if (keycode == 27) { + exitYesNoPanelMode(); + } else if (_textField.enabled) { + updateTextField(ascii, keycode); + } + break; + case PM_NORMAL: + if (keycode == 27) { + _quitMode = QM_CONTINUE; + } + break; + } +} + +void Journal::handleMouseWheel(int inc) { + if (_panelMode == PM_NORMAL) { + int curSave = _currentSavePage * NUM_SAVES_PER_PAGE + _currentSaveSlot + inc; + if (curSave >= 0 && curSave < NUM_SAVES_PER_PAGE * 10) { + _currentSavePage = curSave / NUM_SAVES_PER_PAGE; + _currentSaveSlot = curSave % NUM_SAVES_PER_PAGE; + drawSaveDescriptions(); + drawSaveSlot(); + update(); + } + } +} + +void Journal::handleMouseDown(int x, int y) { + int val; + int16 zoneNum = _vm->grid()->findZoneForPos(GS_ROOM, x, y); + switch (_panelMode) { + case PM_INFO_BOX: + exitInfoPanelMode(); + break; + case PM_YES_NO: + if (zoneNum == ZN_YES) { + _panelMode = PM_NORMAL; + int currentSlot = _currentSavePage * 10 + _currentSaveSlot; + switch (_prevZoneNum) { + case ZN_REVIEW_ENTRY: + if (_saveDescriptions[currentSlot][0]) { + _vm->graphics()->clearBobs(); + _vm->display()->palFadeOut(ROOM_JOURNAL); + _vm->music()->stopSong(); + _vm->loadGameState(currentSlot); + _vm->display()->clearTexts(0, GAME_SCREEN_HEIGHT - 1); + _quitMode = QM_RESTORE; + } else { + exitYesNoPanelMode(); + } + break; + case ZN_MAKE_ENTRY: + if (_textField.text[0]) { + closeTextField(); + _vm->saveGameState(currentSlot, _textField.text); + _quitMode = QM_CONTINUE; + } else { + exitYesNoPanelMode(); + } + break; + case ZN_GIVEUP: + _quitMode = QM_CONTINUE; + _vm->quitGame(); + break; + } + } else if (zoneNum == ZN_NO) { + exitYesNoPanelMode(); + } + break; + case PM_NORMAL: + switch (zoneNum) { + case ZN_REVIEW_ENTRY: + enterYesNoPanelMode(zoneNum, TXT_REVIEW_ENTRY); + break; + case ZN_MAKE_ENTRY: + initTextField(_saveDescriptions[_currentSavePage * 10 + _currentSaveSlot]); + enterYesNoPanelMode(zoneNum, TXT_MAKE_ENTRY); + break; + case ZN_CLOSE: + _quitMode = QM_CONTINUE; + break; + case ZN_GIVEUP: + enterYesNoPanelMode(zoneNum, TXT_GIVE_UP); + break; + case ZN_TEXT_SPEED: + val = (x - 136) * QueenEngine::MAX_TEXT_SPEED / (266 - 136); + _vm->talkSpeed(val); + drawConfigPanel(); + break; + case ZN_SFX_TOGGLE: + _vm->sound()->toggleSfx(); + drawConfigPanel(); + break; + case ZN_MUSIC_VOLUME: + val = (x - 136) * QueenEngine::MAX_MUSIC_VOLUME / (266 - 136); + _vm->music()->setVolume(val); + drawConfigPanel(); + break; + case ZN_DESC_1: + case ZN_DESC_2: + case ZN_DESC_3: + case ZN_DESC_4: + case ZN_DESC_5: + case ZN_DESC_6: + case ZN_DESC_7: + case ZN_DESC_8: + case ZN_DESC_9: + case ZN_DESC_10: + _currentSaveSlot = zoneNum - ZN_DESC_1; + drawSaveSlot(); + break; + case ZN_PAGE_A: + case ZN_PAGE_B: + case ZN_PAGE_C: + case ZN_PAGE_D: + case ZN_PAGE_E: + case ZN_PAGE_F: + case ZN_PAGE_G: + case ZN_PAGE_H: + case ZN_PAGE_I: + case ZN_PAGE_J: + _currentSavePage = zoneNum - ZN_PAGE_A; + drawSaveDescriptions(); + break; + case ZN_INFO_BOX: + enterInfoPanelMode(); + break; + case ZN_MUSIC_TOGGLE: + _vm->sound()->toggleMusic(); + if (_vm->sound()->musicOn()) { + _vm->sound()->playLastSong(); + } else { + _vm->music()->stopSong(); + } + drawConfigPanel(); + break; + case ZN_VOICE_TOGGLE: + _vm->sound()->toggleSpeech(); + drawConfigPanel(); + break; + case ZN_TEXT_TOGGLE: + _vm->subtitles(!_vm->subtitles()); + drawConfigPanel(); + break; + } + break; + } + update(); +} + +void Journal::drawPanelText(int y, const char *text) { + debug(7, "Journal::drawPanelText(%d, '%s')", y, text); + char s[80]; + strcpy(s, text); + char *p = strchr(s, ' '); + if (p == NULL) { + int x = (128 - _vm->display()->textWidth(s)) / 2; + _vm->display()->setText(x, y, s, false); + assert(_panelTextCount < MAX_PANEL_TEXTS); + _panelTextY[_panelTextCount++] = y; + } else { + *p++ = '\0'; + if (_vm->resource()->getLanguage() == HEBREW) { + drawPanelText(y - 5, p); + drawPanelText(y + 5, s); + } else { + drawPanelText(y - 5, s); + drawPanelText(y + 5, p); + } + } +} + +void Journal::drawCheckBox(bool active, int bobNum, int16 x, int16 y, int frameNum) { + if (active) { + showBob(bobNum, x, y, frameNum); + } else { + hideBob(bobNum); + } +} + +void Journal::drawSlideBar(int value, int maxValue, int bobNum, int16 y, int frameNum) { + showBob(bobNum, 136 + value * (266 - 136) / maxValue, y, frameNum); +} + +void Journal::drawPanel(const int *frames, const int *titles, int n) { + for (int i = 0; i < _panelTextCount; ++i) { + _vm->display()->clearTexts(_panelTextY[i], _panelTextY[i]); + } + _panelTextCount = 0; + int bobNum = 1; + int y = 8; + while (n--) { + showBob(bobNum++, 32, y, *frames++); + drawPanelText(y + 12, _vm->logic()->joeResponse(*titles++)); + y += 48; + } +} + +void Journal::drawNormalPanel() { + static const int frames[] = { FRAME_BLUE_1, FRAME_BLUE_2, FRAME_BLUE_1, FRAME_ORANGE }; + static const int titles[] = { TXT_REVIEW_ENTRY, TXT_MAKE_ENTRY, TXT_CLOSE, TXT_GIVE_UP }; + drawPanel(frames, titles, 4); +} + +void Journal::drawYesNoPanel(int titleNum) { + static const int frames[] = { FRAME_GREY, FRAME_BLUE_1, FRAME_BLUE_2 }; + const int titles[] = { titleNum, TXT_YES, TXT_NO }; + drawPanel(frames, titles, 3); + + hideBob(BOB_LEFT_RECT_4); + hideBob(BOB_TALK_SPEED); + hideBob(BOB_SFX_TOGGLE); + hideBob(BOB_MUSIC_VOLUME); + hideBob(BOB_SPEECH_TOGGLE); + hideBob(BOB_TEXT_TOGGLE); + hideBob(BOB_MUSIC_TOGGLE); +} + +void Journal::drawConfigPanel() { + _vm->checkOptionSettings(); + + drawSlideBar(_vm->talkSpeed(), QueenEngine::MAX_TEXT_SPEED, BOB_TALK_SPEED, 164, FRAME_BLUE_PIN); + drawSlideBar(_vm->music()->volume(), QueenEngine::MAX_MUSIC_VOLUME, BOB_MUSIC_VOLUME, 177, FRAME_GREEN_PIN); + + drawCheckBox(_vm->sound()->sfxOn(), BOB_SFX_TOGGLE, 221, 155, FRAME_CHECK_BOX); + drawCheckBox(_vm->sound()->speechOn(), BOB_SPEECH_TOGGLE, 158, 155, FRAME_CHECK_BOX); + drawCheckBox(_vm->subtitles(), BOB_TEXT_TOGGLE, 125, 167, FRAME_CHECK_BOX); + drawCheckBox(_vm->sound()->musicOn(), BOB_MUSIC_TOGGLE, 125, 181, FRAME_CHECK_BOX); +} + +void Journal::drawInfoPanel() { + showBob(BOB_INFO_BOX, 72, 221, FRAME_INFO_BOX); + const char *ver = _vm->resource()->JASVersion(); + switch (ver[0]) { + case 'P': + _vm->display()->setTextCentered(132, "PC Hard Drive", false); + break; + case 'C': + _vm->display()->setTextCentered(132, "PC CD-ROM", false); + break; + case 'a': + _vm->display()->setTextCentered(132, "Amiga A500/600", false); + break; + case 'A': + _vm->display()->setTextCentered(132, "Amiga A1200", false); + break; + case 'c': + _vm->display()->setTextCentered(132, "Amiga CD-32", false); + break; + } + switch (ver[1]) { + case 'E': + _vm->display()->setTextCentered(144, "English", false); + break; + case 'F' : + _vm->display()->setTextCentered(144, "Fran\x87""ais", false); + break; + case 'G': + _vm->display()->setTextCentered(144, "Deutsch", false); + break; + case 'H': + _vm->display()->setTextCentered(144, "Hebrew", false); + break; + case 'I': + _vm->display()->setTextCentered(144, "Italiano", false); + break; + case 'S': + _vm->display()->setTextCentered(144, "Espa\xA4""ol", false); + break; + } + char versionId[13]; + sprintf(versionId, "Version %c.%c%c", ver[2], ver[3], ver[4]); + _vm->display()->setTextCentered(156, versionId, false); +} + +void Journal::initTextField(const char *desc) { + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + _textField.enabled = true; + _textField.posCursor = _vm->display()->textWidth(desc); + _textField.textCharsCount = strlen(desc); + memset(_textField.text, 0, sizeof(_textField.text)); + strcpy(_textField.text, desc); +} + +void Journal::updateTextField(uint16 ascii, int keycode) { + bool dirty = false; + switch (keycode) { + case 8: // backspace + if (_textField.textCharsCount > 0) { + --_textField.textCharsCount; + _textField.text[_textField.textCharsCount] = '\0'; + dirty = true; + } + break; + case '\n': + case '\r': + if (_textField.text[0]) { + closeTextField(); + int currentSlot = _currentSavePage * 10 + _currentSaveSlot; + _vm->saveGameState(currentSlot, _textField.text); + _quitMode = QM_CONTINUE; + } + break; + default: + if (isprint((char)ascii) && + _textField.textCharsCount < (sizeof(_textField.text) - 1) && + _vm->display()->textWidth(_textField.text) < _textField.w) { + _textField.text[_textField.textCharsCount] = (char)ascii; + ++_textField.textCharsCount; + dirty = true; + } + break; + } + if (dirty) { + _vm->display()->setText(_textField.x, _textField.y + _currentSaveSlot * _textField.h, _textField.text, false); + _textField.posCursor = _vm->display()->textWidth(_textField.text); + update(); + } +} + +void Journal::closeTextField() { + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + _textField.enabled = false; +} + +const Journal::Zone Journal::_zones[] = { + { ZN_REVIEW_ENTRY, 32, 8, 96, 40 }, + { ZN_MAKE_ENTRY, 32, 56, 96, 88 }, // == ZN_YES + { ZN_CLOSE, 32, 104, 96, 136 }, // == ZN_NO + { ZN_GIVEUP, 32, 152, 96, 184 }, + { ZN_TEXT_SPEED, 136, 169, 265, 176 }, + { ZN_SFX_TOGGLE, 197, 155, 231, 164 }, + { ZN_MUSIC_VOLUME, 136, 182, 265, 189 }, + { ZN_DESC_1, 131, 7, 290, 18 }, + { ZN_DESC_2, 131, 20, 290, 31 }, + { ZN_DESC_3, 131, 33, 290, 44 }, + { ZN_DESC_4, 131, 46, 290, 57 }, + { ZN_DESC_5, 131, 59, 290, 70 }, + { ZN_DESC_6, 131, 72, 290, 83 }, + { ZN_DESC_7, 131, 85, 290, 96 }, + { ZN_DESC_8, 131, 98, 290, 109 }, + { ZN_DESC_9, 131, 111, 290, 122 }, + { ZN_DESC_10, 131, 124, 290, 135 }, + { ZN_PAGE_A, 300, 4, 319, 17 }, + { ZN_PAGE_B, 300, 19, 319, 32 }, + { ZN_PAGE_C, 300, 34, 319, 47 }, + { ZN_PAGE_D, 300, 49, 319, 62 }, + { ZN_PAGE_E, 300, 64, 319, 77 }, + { ZN_PAGE_F, 300, 79, 319, 92 }, + { ZN_PAGE_G, 300, 94, 319, 107 }, + { ZN_PAGE_H, 300, 109, 319, 122 }, + { ZN_PAGE_I, 300, 124, 319, 137 }, + { ZN_PAGE_J, 300, 139, 319, 152 }, + { ZN_INFO_BOX, 273, 146, 295, 189 }, + { ZN_MUSIC_TOGGLE, 109, 181, 135, 190 }, + { ZN_VOICE_TOGGLE, 134, 155, 168, 164 }, + { ZN_TEXT_TOGGLE, 109, 168, 135, 177 } +}; + +} // End of namespace Queen |