/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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 3 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, see . * */ #include "immortal/immortal.h" namespace Immortal { /* * * ----- ----- * ----- Main Functions ----- * ----- ----- * */ void ImmortalEngine::miscInit() { // In the source, this is where the seed for the rng is set, but we don't need to do that as we used _randomSource _lastGauge = 0; } void ImmortalEngine::setRandomSeed() {} void ImmortalEngine::getRandom() {} /* * * ----- ----- * ----- Text Printing ----- * ----- ----- * */ // myFadeOut and myFadeIn are just RTS in the source, but they are called quite a lot void ImmortalEngine::myFadeOut() { return; } void ImmortalEngine::myFadeIn() { return; } bool ImmortalEngine::textPrint(Str s, int n) { _slowText = 0; _formatted = 0; _collumn = 0; _row = 0; playTextSong(); clearScreen(); return textSub(s, kTextFadeIn, n); } bool ImmortalEngine::textBeginning(Str s, int n) { _slowText = 0; _formatted = 0; _collumn = 0; _row = 0; playTextSong(); clearScreen(); return textSub(s, kTextDontFadeIn, n); } void ImmortalEngine::textEnd(Str s, int n) { textSub(s, kTextFadeIn, n); } void ImmortalEngine::textMiddle(Str s, int n) { textSub(s, kTextDontFadeIn, n); } bool ImmortalEngine::textSub(Str s, FadeType f, int n) { bool done = false; char chr = 0; int index = 0; Common::String text = _strPtrs[s]; while (done == false) { switch (text[index]) { case '@': case '=': case char(0): done = true; // This is so the while loop can be a little cleaner index--; break; case '&': textCR(); break; case '$': printByte(n); copyToScreen(); break; case '_': myFadeIn(); _slowText = 1; break; case '<': _slowText = 0; break; case '>': _formatted = 0; break; case '\\': normalFadeOut(); break; case '/': slowFadeOut(); break; case '|': normalFadeIn(); break; case '}': _formatted = 1; break; case ']': myDelay(40); break; case '{': index++; myDelay(text[index]); break; case '*': textPageBreak(text, index); break; case '[': textAutoPageBreak(); break; case '#': index++; drawIcon(text[index]); break; case '~': text = _strPtrs[(int)text[index + 1]]; index = -1; break; case '^': center(); break; case '%': return yesNo(); case '+': chr = 0x27; break; case '(': chr = 0x60; break; default: chr = text[index]; _collumn++; if (chr == ' ') { if (text[index + 1] == '~') { text = _strPtrs[(int)text[index + 2]]; index = -1; } textDoSpace(text, index); } else { printChr(chr); // We need this to show up now, not when the frame ends, so we have to update the screen here copyToScreen(); if (_slowText != 0) { myDelay(5); switch (chr) { case '?': // fall through case ':': myDelay(13); // fall through case '.': myDelay(13); // fall through case ',': myDelay(13); // fall through default: break; } } } break; } if (index == 0xFF) { debug("String too long!"); return false; } index++; } chr = text[index]; if (f != kTextFadeIn) { return false; } // If we need to display an 'OK' message if (chr != '=') { setPen(_penX, kYesNoY); center(); drawIcon(kOkayFrame); copyToScreen(); if (_slowText == 0) { myFadeIn(); } waitClick(); standardBeep(); textBounceDelay(); } else if (_slowText == 0) { myFadeIn(); } return false; } void ImmortalEngine::textCR() { carriageReturn(); _row++; _collumn = 0; } void ImmortalEngine::textPageBreak(Common::String s, int &index) { _collumn = 0; _row = 0; if (_slowText == 0) { myFadeIn(); } index++; myDelay((int) s[index]); myFadeOut(); clearScreen(); if (_slowText != 0) { myFadeIn(); } } void ImmortalEngine::textAutoPageBreak() { _collumn = 0; _row = 0; if (_slowText == 0) { myFadeIn(); } myDelay(140); myFadeOut(); clearScreen(); if (_slowText != 0) { myFadeIn(); } } void ImmortalEngine::textDoSpace(Common::String s, int index) { // If text is formatted, then check if the space between here and the end of the string will fit, if not, use a newline or pagebreak if (_formatted != 0) { bool foundEnd = false; int start = index; while (foundEnd == false) { index++; switch (s[index]) { case '=': // fall through case '@': // fall through case '%': // fall through case '[': // fall through case ' ': foundEnd = true; // fall through default: break; } } if (((index - start) + _collumn) >= kMaxCollumns) { if (_row < kMaxRows) { textCR(); } else { textAutoPageBreak(); } return; } } printChr(' '); } void ImmortalEngine::textBounceDelay() { Utilities::delay(7); } bool ImmortalEngine::yesNo() { uint8 tyes[9] = {0, 1, 1, 1, 0, 0, 0, 0, 0}; getInput(); if (tyes[_heldDirection] == 0) { noOn(); _lastYes = 0; } else { yesOn(); _lastYes = 1; } while (buttonPressed() || firePressed()) { // If they have not pressed a button yet, we get the input after a delay Utilities::delay(4); getInput(); // And then if they have changed direction, we play a sound and update the direction and button gfx if (tyes[_heldDirection] != _lastYes) { _lastYes = tyes[_heldDirection]; standardBeep(); if (_lastYes == 0) { noOn(); } else { yesOn(); } // Since we need this to show up right during the text sequence, we need to update the screen copyToScreen(); } } standardBeep(); textBounceDelay(); // In source this is done weirdly so that it can use a result in A, except it never uses that result, so it's just weird. return (!(bool) _lastYes); } void ImmortalEngine::noOn() { // Draw the No icon as on, and the Yes icon as off setPen(kYesNoX1, kYesNoY); drawIcon(kNoIconOn); setPen(kYesNoX2, kYesNoY); drawIcon(kYesIconOff); } void ImmortalEngine::yesOn() { // Draw the No icon as off, and the Yes icon as on setPen(kYesNoX1, kYesNoY); drawIcon(kNoIconOff); setPen(kYesNoX2, kYesNoY); drawIcon(kYesIconOn); } void ImmortalEngine::myDelay(int j) { int type = 0; // Update input getInput(); // 0 = neither button held, 1 = one held, 2 = both held if (_heldAction & kActionButton) { type++; } if (_heldAction & kActionFire) { type++; } do { // If the button was *pressed* and not held, then skip any delay if (!buttonPressed()) { return; } if (!firePressed()) { return; } // Otherwise, we delay by different amounts based on what's held down switch (type) { case 1: Utilities::delay4(1); break; case 0: Utilities::delay(1); // fall through case 2: // fall through default: break; } j--; } while (j != 0); } /* * * ----- ----- * ----- Input Related ----- * ----- ----- * */ bool ImmortalEngine::buttonPressed() { // Returns false if the button was pressed, but not held or up getInput(); if (_heldAction == kActionButton) { // Zero just the button0held bit _myButton &= (0xFF - kButton0Held); } else if ((_myButton & kButton0Held) == 0) { _myButton |= kButton0Held; return false; } return true; } bool ImmortalEngine::firePressed() { // Returns false if the button was pressed, but not held or up getInput(); if (_heldAction == kActionFire) { _myButton &= (0xFF - kButton1Held); } else if ((_myButton & kButton1Held) == 0) { _myButton |= kButton1Held; return false; } return true; } /* * * ----- ----- * ----- Screen Related ----- * ----- ----- * */ /* * * ----- ----- * ----- Sound Related ----- * ----- ----- * */ void ImmortalEngine::standardBeep() { //playNote(4, 5, 0x4C); } } // namespace Immortal