From 91de740d44710835f9b48f9f7ce787aeea6094df Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 26 Dec 2008 11:04:45 +0000 Subject: Implemented (some) main menu code for LoL. svn-id: r35553 --- engines/kyra/gui.cpp | 19 ++-- engines/kyra/gui.h | 9 +- engines/kyra/kyra_hof.cpp | 63 +----------- engines/kyra/kyra_hof.h | 2 - engines/kyra/kyra_mr.cpp | 6 +- engines/kyra/lol.cpp | 211 +++++++++++++++++++++++++++++++++++++++-- engines/kyra/lol.h | 18 ++++ engines/kyra/module.mk | 1 + engines/kyra/sequences_hof.cpp | 6 +- engines/kyra/staticres.cpp | 14 ++- 10 files changed, 260 insertions(+), 89 deletions(-) (limited to 'engines') diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index b316d727bd..f03f028b98 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -441,10 +441,11 @@ int MainMenu::handle(int dim) { memset(colorMap, 0, sizeof(colorMap)); _screen->setTextColorMap(colorMap); - Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT); + Screen::FontId oldFont = _screen->setFont(_static.font); int charWidthBackUp = _screen->_charWidth; - _screen->_charWidth = -2; + if (_vm->game() != GI_LOL) + _screen->_charWidth = -2; _screen->setScreenDim(dim); while (!_screen->isMouseVisible()) @@ -473,7 +474,7 @@ int MainMenu::handle(int dim) { int fh = _screen->getFontHeight(); int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3; - Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4); + Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * _static.menuTable[3]); while (!_vm->shouldQuit()) { updateAnimation(); @@ -484,18 +485,18 @@ int MainMenu::handle(int dim) { int item = (mouse.y - menuRect.top) / fh; if (item != selected) { - printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.colorNormal, 0, 5); - printString(_static.strings[item], textPos, menuRect.top + item * fh, _static.colorFlash, 0, 5); + printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.menuTable[5], 0, 5); + printString(_static.strings[item], textPos, menuRect.top + item * fh, _static.menuTable[6], 0, 5); selected = item; } if (mousePressed) { for (int i = 0; i < 3; i++) { - printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.colorNormal, 0, 5); + printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.menuTable[5], 0, 5); _screen->updateScreen(); _system->delayMillis(50); - printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.colorFlash, 0, 5); + printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.menuTable[6], 0, 5); _screen->updateScreen(); _system->delayMillis(50); } @@ -562,8 +563,8 @@ void MainMenu::printString(const char *format, int x, int y, int col1, int col2, x -= _screen->getTextWidth(string); if (flags & 4) { - _screen->printText(string, x - 1, y, 240, col2); - _screen->printText(string, x, y + 1, 240, col2); + _screen->printText(string, x - 1, y, _static.altColor, col2); + _screen->printText(string, x, y + 1, _static.altColor, col2); } if (flags & 8) { diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h index 8115d91e7a..2ee764bfbe 100644 --- a/engines/kyra/gui.h +++ b/engines/kyra/gui.h @@ -27,6 +27,7 @@ #define KYRA_GUI_H #include "kyra/kyra_v1.h" +#include "kyra/screen.h" #include "common/ptr.h" #include "common/array.h" @@ -217,11 +218,13 @@ public: }; struct StaticData { - const char *strings[4]; + const char *strings[5]; - uint8 menuTable[11]; + uint8 menuTable[7]; uint8 colorTable[4]; - uint8 colorNormal, colorFlash; + + Screen::FontId font; + uint8 altColor; }; void init(StaticData data, Animation anim); diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index efe3394885..316e341a14 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -34,6 +34,7 @@ #include "kyra/text_hof.h" #include "kyra/timer.h" #include "kyra/debugger.h" +#include "kyra/util.h" #include "common/system.h" #include "common/config-manager.h" @@ -888,8 +889,8 @@ char *KyraEngine_HoF::getTableString(int id, uint8 *buffer, int decode) { char *string = (char*)getTableEntry(buffer, id); if (decode && _flags.lang != Common::JA_JPN) { - decodeString1(string, _internStringBuf); - decodeString2(_internStringBuf, _internStringBuf); + Util::decodeString1(string, _internStringBuf); + Util::decodeString2(_internStringBuf, _internStringBuf); string = _internStringBuf; } @@ -903,64 +904,6 @@ const char *KyraEngine_HoF::getChapterString(int id) { return getTableString(id, _chapterBuffer, 1); } -int KyraEngine_HoF::decodeString1(const char *src, char *dst) { - static const uint8 decodeTable1[] = { - 0x20, 0x65, 0x74, 0x61, 0x69, 0x6E, 0x6F, 0x73, 0x72, 0x6C, 0x68, - 0x63, 0x64, 0x75, 0x70, 0x6D - }; - - static const uint8 decodeTable2[] = { - 0x74, 0x61, 0x73, 0x69, 0x6F, 0x20, 0x77, 0x62, 0x20, 0x72, 0x6E, - 0x73, 0x64, 0x61, 0x6C, 0x6D, 0x68, 0x20, 0x69, 0x65, 0x6F, 0x72, - 0x61, 0x73, 0x6E, 0x72, 0x74, 0x6C, 0x63, 0x20, 0x73, 0x79, 0x6E, - 0x73, 0x74, 0x63, 0x6C, 0x6F, 0x65, 0x72, 0x20, 0x64, 0x74, 0x67, - 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x72, 0x20, 0x75, 0x66, 0x6D, 0x73, - 0x77, 0x20, 0x74, 0x65, 0x70, 0x2E, 0x69, 0x63, 0x61, 0x65, 0x20, - 0x6F, 0x69, 0x61, 0x64, 0x75, 0x72, 0x20, 0x6C, 0x61, 0x65, 0x69, - 0x79, 0x6F, 0x64, 0x65, 0x69, 0x61, 0x20, 0x6F, 0x74, 0x72, 0x75, - 0x65, 0x74, 0x6F, 0x61, 0x6B, 0x68, 0x6C, 0x72, 0x20, 0x65, 0x69, - 0x75, 0x2C, 0x2E, 0x6F, 0x61, 0x6E, 0x73, 0x72, 0x63, 0x74, 0x6C, - 0x61, 0x69, 0x6C, 0x65, 0x6F, 0x69, 0x72, 0x61, 0x74, 0x70, 0x65, - 0x61, 0x6F, 0x69, 0x70, 0x20, 0x62, 0x6D - }; - - int size = 0; - uint cChar = 0; - while ((cChar = *src++) != 0) { - if (cChar & 0x80) { - cChar &= 0x7F; - int index = (cChar & 0x78) >> 3; - *dst++ = decodeTable1[index]; - ++size; - assert(cChar < sizeof(decodeTable2)); - cChar = decodeTable2[cChar]; - } - - *dst++ = cChar; - ++size; - } - - *dst++ = 0; - return size; -} - -void KyraEngine_HoF::decodeString2(const char *src, char *dst) { - if (!src || !dst) - return; - - char out = 0; - while ((out = *src) != 0) { - if (*src == 0x1B) { - ++src; - out = *src + 0x7F; - } - *dst++ = out; - ++src; - } - - *dst = 0; -} - #pragma mark - void KyraEngine_HoF::showMessageFromCCode(int id, int16 palIndex, int) { diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index a3f78b8465..31dc38b110 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -551,8 +551,6 @@ protected: uint8 *getTableEntry(uint8 *buffer, int id); char *getTableString(int id, uint8 *buffer, int decode); const char *getChapterString(int id); - int decodeString1(const char *src, char *dst); - void decodeString2(const char *src, char *dst); void changeFileExtension(char *buffer); diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 823b253534..6e5bba3dc0 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -337,10 +337,10 @@ void KyraEngine_MR::initMainMenu() { _menu = new MainMenu(this); MainMenu::StaticData data = { - { _mainMenuStrings[_lang*4+0], _mainMenuStrings[_lang*4+1], _mainMenuStrings[_lang*4+2], _mainMenuStrings[_lang*4+3] }, - { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 }, + { _mainMenuStrings[_lang*4+0], _mainMenuStrings[_lang*4+1], _mainMenuStrings[_lang*4+2], _mainMenuStrings[_lang*4+3], 0 }, + { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF }, { 0x16, 0x19, 0x1A, 0x16 }, - 0x80, 0xFF + Screen::FID_8_FNT, 240 }; if (_flags.lang == Common::ES_ESP) { diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 9dfb7994e1..1c70fe96d3 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -27,6 +27,7 @@ #include "kyra/screen_lol.h" #include "kyra/resource.h" #include "kyra/sound.h" +#include "kyra/util.h" #include "common/endian.h" @@ -55,13 +56,19 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _lang = 0; break; } + + memset(_shapes, 0, sizeof(_shapes)); _chargenWSA = 0; + _lastUsedStringBuffer = 0; } LoLEngine::~LoLEngine() { setupPrologueData(false); + for (uint i = 0; i < ARRAYSIZE(_shapes); ++i) + delete[] _shapes[i]; + delete _screen; delete _tim; @@ -94,20 +101,206 @@ Common::Error LoLEngine::init() { } Common::Error LoLEngine::go() { - setupPrologueData(true); - showIntro(); - _sound->playTrack(6); - /*int character = */chooseCharacter(); - _sound->playTrack(1); - _screen->fadeToBlack(); - setupPrologueData(false); + bool hasSave = saveFileLoadable(0); + + if (!hasSave) { + setupPrologueData(true); + showIntro(); + setupPrologueData(false); + } + + preInit(); + + int processSelection = -1; + while (!shouldQuit() && processSelection == -1) { + _screen->loadBitmap("TITLE.CPS", 2, 2, _screen->getPalette(0)); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); + _screen->fadePalette(_screen->getPalette(0), 0x1E); + + int selection = mainMenu(); + + switch (selection) { + case 0: // New game + processSelection = 0; + break; + + case 1: // Show intro + setupPrologueData(true); + _screen->hideMouse(); + showIntro(); + _screen->showMouse(); + setupPrologueData(false); + break; + + case 2: // "Lore of the Lands" + break; + + case 3: // Load game + // For now fall through + //processSelection = 3; + //break; + + case 4: // Quit game + default: + quitGame(); + break; + } + } + + if (processSelection == -1) + return Common::kNoError; + + if (processSelection == 0) { + // Unlike the original, we add a nice fade to black + memset(_screen->getPalette(0), 0, 768); + _screen->fadePalette(_screen->getPalette(0), 0x54); + + setupPrologueData(true); + _sound->loadSoundFile("LOREINTR"); + _sound->playTrack(6); + /*int character = */chooseCharacter(); + _sound->playTrack(1); + _screen->fadeToBlack(); + setupPrologueData(false); + } else if (processSelection == 3) { + //XXX + } return Common::kNoError; } +#pragma mark - Initialization + +void LoLEngine::preInit() { + debugC(9, kDebugLevelMain, "LoLEngine::preInit()"); + + _res->loadFileList("FILEDATA.FDT"); + _screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT"); + _screen->loadFont(Screen::FID_6_FNT, "FONT6P.FNT"); + + uint8 *pal = _screen->getPalette(0); + memset(pal, 0, 768); + _screen->setScreenPalette(pal); + + /*if (_sound->getMusicType() == Sound::kMidiMT32 || _sound->getSfxType() == Sound::kMidiMT32) { + _sound->loadSoundFile("LOLSYSEX"); + _sound->playTrack(0); + + while (_sound->isPlaying() && !shouldQuit()) + delay(10); + }*/ + + if (shouldQuit()) + return; + + _eventList.clear(); + + //loadTalkFile(0); + + char filename[32]; + snprintf(filename, sizeof(filename), "LANDS.%s", _languageExt[_lang]); + _landsFile = _res->fileData(filename, 0); + + initializeCursors(); + + /*_screen->setFont(Screen::FID_6_FNT); + _screen->fprintString("V CD1.02 D", 260, 301, 0x67, 0x00, 0x04);*/ + _screen->setFont(Screen::FID_9_FNT); +} + +void LoLEngine::initializeCursors() { + debugC(9, kDebugLevelMain, "LoLEngine::initializeCursors()"); + + _screen->loadBitmap("ITEMICN.SHP", 3, 3, 0); + _shapes[0] = _screen->makeShapeCopy(_screen->getCPagePtr(3), 0); + _screen->setMouseCursor(0, 0, _shapes[0]); +} + + +int LoLEngine::mainMenu() { + debugC(9, kDebugLevelMain, "LoLEngine::mainMenu()"); + + bool hasSave = saveFileLoadable(0); + + MainMenu::StaticData data = { + { 0, 0, 0, 0, 0 }, + { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F }, + { 0x2C, 0x19, 0x48, 0x2C }, + Screen::FID_9_FNT, 1 + }; + + if (hasSave) + ++data.menuTable[3]; + + static const uint16 mainMenuStrings[2][5] = { + { 0x4248, 0x4249, 0x42DD, 0x424A, 0x0000 }, + { 0x4248, 0x4249, 0x42DD, 0x4001, 0x424A } + }; + + for (int i = 0; i < 5; ++i) { + if (hasSave) + data.strings[i] = getLangString(mainMenuStrings[1][i]); + else + data.strings[i] = getLangString(mainMenuStrings[0][i]); + } + + MainMenu *menu = new MainMenu(this); + assert(menu); + menu->init(data, MainMenu::Animation()); + + int selection = menu->handle(hasSave ? 12 : 6); + delete menu; + + if (!hasSave && selection == 3) + selection = 4; + + return selection; +} + +#pragma mark - Localization + +const char *LoLEngine::getLangString(uint16 id) { + debugC(9, kDebugLevelMain, "LoLEngine::getLangString(0x%.04X)", id); + + if (id == 0xFFFF) + return 0; + + uint16 realId = id & 0x3FFF; + uint8 *buffer = 0; + + if (id & 0x4000) + buffer = _landsFile; + else + buffer = 0; // TODO + + if (!buffer) + return 0; + + const char *string = (const char *)getTableEntry(buffer, realId); + + char *srcBuffer = _stringBuffer[_lastUsedStringBuffer]; + Util::decodeString1(string, srcBuffer); + Util::decodeString2(srcBuffer, srcBuffer); + + ++_lastUsedStringBuffer; + _lastUsedStringBuffer %= ARRAYSIZE(_stringBuffer); + + return srcBuffer; +} + +uint8 *LoLEngine::getTableEntry(uint8 *buffer, uint16 id) { + debugC(9, kDebugLevelMain, "LoLEngine::getTableEntry(%p, %d)", (const void *)buffer, id); + if (!buffer) + return 0; + + return buffer + READ_LE_UINT16(buffer + (id<<1)); +} + #pragma mark - Intro void LoLEngine::setupPrologueData(bool load) { + debugC(9, kDebugLevelMain, "LoLEngine::setupPrologueData(%d)", load); + static const char * const fileList[] = { "GENERAL.PAK", "INTROVOC.PAK", "STARTUP.PAK", "INTRO1.PAK", "INTRO2.PAK", "INTRO3.PAK", "INTRO4.PAK", "INTRO5.PAK", @@ -132,6 +325,9 @@ void LoLEngine::setupPrologueData(bool load) { _res->unloadPakFile(filename); } } + + _screen->clearPage(0); + _screen->clearPage(3); if (load) { _chargenWSA = new WSAMovie_v2(this, _screen); @@ -189,7 +385,6 @@ void LoLEngine::showIntro() { _screen->showMouse(); _sound->voiceStop(); - // HACK: Remove all input events _eventList.clear(); _tim->unload(intro); diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 9e5f29902e..a984fdc36f 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -50,6 +50,13 @@ private: Common::Error init(); Common::Error go(); + // initialization + void preInit(); + + void initializeCursors(); + + int mainMenu(); + // intro void setupPrologueData(bool load); @@ -118,7 +125,18 @@ private: // translation int _lang; + uint8 *_landsFile; + + int _lastUsedStringBuffer; + char _stringBuffer[5][512]; // TODO: The original used a size of 512, it looks a bit large. + // Maybe we can someday reduce the size. + const char *getLangString(uint16 id); + uint8 *getTableEntry(uint8 *buffer, uint16 id); + static const char * const _languageExt[]; + + // graphics + uint8 *_shapes[138]; // unneeded void setWalkspeed(uint8) {} diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index 8169b7b33f..18ab2ecdb5 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -67,6 +67,7 @@ MODULE_OBJS := \ timer_lok.o \ timer_hof.o \ timer_mr.o \ + util.o \ vqa.o \ wsamovie.o diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 718c8dadfa..7d0feaed16 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -2853,10 +2853,10 @@ void KyraEngine_HoF::seq_init() { } while (getShapePtr(numShp)); } else { MainMenu::StaticData data = { - { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98] }, - { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xd7, 0xd6, 0x00, 0x01, 0x02, 0x03 }, + { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98], 0 }, + { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xd7, 0xd6 }, { 0xd8, 0xda, 0xd9, 0xd8 }, - 0xd7, 0xd6 + Screen::FID_8_FNT, 240 }; _menu = new MainMenu(this); _menu->init(data, MainMenu::Animation()); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index bd94fe3f25..ca03451201 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -2357,7 +2357,19 @@ const int8 KyraEngine_MR::_albumWSAY[] = { // lands of lore static res const ScreenDim Screen_LoL::_screenDimTable[] = { - { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 } + { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, // Taken from Intro + { 0x08, 0x48, 0x18, 0x38, 0xFE, 0x01, 0x00, 0x00 }, + { 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 }, + { 0x0B, 0x7B, 0x1C, 0x12, 0xFE, 0xFC, 0x00, 0x00 }, + { 0x0B, 0x7B, 0x1C, 0x2D, 0xFE, 0xFC, 0x00, 0x00 }, + { 0x55, 0x7B, 0xE9, 0x37, 0xFE, 0xFC, 0x00, 0x00 }, + { 0x0B, 0x8C, 0x10, 0x2B, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries) + { 0x04, 0x59, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 }, + { 0x05, 0x6E, 0x1E, 0x0C, 0xFE, 0x01, 0x00, 0x00 }, + { 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 }, + { 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 }, + { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 } // Main menu box (4 entries) }; const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable); -- cgit v1.2.3