diff options
Diffstat (limited to 'engines')
334 files changed, 30695 insertions, 32850 deletions
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index f526c51a27..cd6942f9c0 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -2148,7 +2148,7 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common: } const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const FSList *fslist) const { - typedef Common::HashMap<Common::String, int32, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> IntMap; + typedef Common::HashMap<Common::String, int32> IntMap; IntMap allFiles; bool matchedUsingFilenames = false; bool matchedUsingWag = false; diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 6944eee9f2..08f8969ca3 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -238,7 +238,7 @@ bool Mickey::checkMenu() { memcpy(buffer, &menu, sizeof(MSA_MENU)); getMenuSel(buffer, &iSel0, &iSel1); - delete [] buffer; + delete[] buffer; return parse(menu.cmd[iSel0].data[iSel1], menu.arg[iSel0].data[iSel1]); } @@ -645,7 +645,7 @@ void Mickey::playSound(ENUM_MSA_SOUND iSound) { case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONUP: case Common::EVENT_KEYDOWN: - delete [] buffer; + delete[] buffer; return; default: break; @@ -657,7 +657,7 @@ void Mickey::playSound(ENUM_MSA_SOUND iSound) { break; } - delete [] buffer; + delete[] buffer; } // Graphics @@ -893,7 +893,7 @@ void Mickey::drawLogo() { _vm->_picture->showPic(10, 10, w, h); - delete [] buffer; + delete[] buffer; } void Mickey::animate() { diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 015aff3458..9b22240f83 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -23,7 +23,7 @@ * */ - +#include <time.h> // for AGOSEngine::getTime() #include "common/config-manager.h" #include "common/file.h" @@ -38,8 +38,6 @@ #include "sound/mididrv.h" #include "sound/mods/protracker.h" -#include <time.h> // for AGOSEngine::getTime() - using Common::File; namespace AGOS { @@ -879,7 +877,7 @@ AGOSEngine::~AGOSEngine() { _midi.close(); for (uint i = 0; i < _itemHeap.size(); i++) { - delete [] _itemHeap[i]; + delete[] _itemHeap[i]; } _itemHeap.clear(); @@ -908,7 +906,7 @@ AGOSEngine::~AGOSEngine() { delete _dummyItem3; delete _dummyWindow; - delete [] _windowList; + delete[] _windowList; delete _debugger; delete _moviePlay; @@ -919,25 +917,31 @@ GUI::Debugger *AGOSEngine::getDebugger() { return _debugger; } -void AGOSEngine::pause() { - _keyPressed.reset(); - _pause = true; - bool ambient_status = _ambientPaused; - bool music_status = _musicPaused; +void AGOSEngine::pauseEngineIntern(bool pauseIt) { + if (pauseIt) { + _keyPressed.reset(); + _pause = true; + + _midi.pause(true); + _mixer->pauseAll(true); + _sound->ambientPause(true); + } else { + _pause = false; + + _midi.pause(_musicPaused); + _mixer->pauseAll(false); + _sound->ambientPause(_ambientPaused); + } +} - _midi.pause(true); - _mixer->pauseAll(true); - _sound->ambientPause(true); +void AGOSEngine::pause() { + pauseEngine(true); while (_pause) { delay(1); if (_keyPressed.keycode == Common::KEYCODE_p) - _pause = false; + pauseEngine(false); } - - _midi.pause(music_status); - _mixer->pauseAll(false); - _sound->ambientPause(ambient_status); } int AGOSEngine::go() { @@ -1017,7 +1021,7 @@ void AGOSEngine::shutdown() { _midi.close(); for (uint i = 0; i < _itemHeap.size(); i++) { - delete [] _itemHeap[i]; + delete[] _itemHeap[i]; } _itemHeap.clear(); @@ -1046,7 +1050,7 @@ void AGOSEngine::shutdown() { delete _dummyItem3; delete _dummyWindow; - delete [] _windowList; + delete[] _windowList; delete _debugger; delete _moviePlay; diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 1d5eda8392..448d26a9d0 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -1205,6 +1205,7 @@ protected: void checkTimerCallback(); void delay(uint delay); void pause(); + virtual void pauseEngineIntern(bool pause); void waitForMark(uint i); void scrollScreen(); diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp index 8a14f677c3..055eb733c3 100644 --- a/engines/cine/anim.cpp +++ b/engines/cine/anim.cpp @@ -53,6 +53,7 @@ AnimData animDataTable[NUM_MAX_ANIMDATA]; static const AnimDataEntry transparencyData[] = { {"ALPHA", 0xF}, + {"TITRE", 0xF}, {"TITRE2", 0xF}, {"ET", 0xC}, {"L311", 0x3}, @@ -380,8 +381,8 @@ void AnimData::save(Common::OutSaveFile &fHandle) const { fHandle.writeUint16BE(_var1); fHandle.writeUint16BE(_bpp); fHandle.writeUint16BE(_height); - fHandle.writeUint32BE(0); // _data - fHandle.writeUint32BE(0); // _mask + fHandle.writeUint32BE(_data != NULL); // _data + fHandle.writeUint32BE(_mask != NULL); // _mask fHandle.writeUint16BE(_fileIdx); fHandle.writeUint16BE(_frameIdx); fHandle.write(_name, sizeof(_name)); @@ -729,7 +730,7 @@ void loadResource(const char *resourceName) { } else if (strstr(resourceName, ".SEQ")) { loadSeq(resourceName, -1); return; - } else if (strstr(resourceName, "ECHEC")) { + } else if (strstr(resourceName, "ECHEC")) { // Echec (French) means failure exitEngine = 1; return; } diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp index b6c07a05cb..c5b7fb4e3d 100644 --- a/engines/cine/bg.cpp +++ b/engines/cine/bg.cpp @@ -37,7 +37,7 @@ uint16 bgVar0; byte *additionalBgTable[9]; byte currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0; -byte loadCt(const char *ctName) { +byte loadCtFW(const char *ctName) { uint16 header[32]; byte *ptr, *dataPtr; @@ -46,79 +46,62 @@ byte loadCt(const char *ctName) { ptr = dataPtr = readBundleFile(findFileInBundle(ctName)); - if (g_cine->getGameType() == Cine::GType_OS) { - uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; - if (bpp == 8) { - ctColorMode = 1; - memcpy(newPalette, ptr, 256 * 3); - ptr += 3 * 256; - memcpy(page3Raw, ptr, 320 * 200); - } else { - ctColorMode = 0; - for (int i = 0; i < 16; i++) { - tempPalette[i] = READ_BE_UINT16(ptr); - ptr += 2; - } - - gfxResetRawPage(page3Raw); - gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200); - } - } else { - loadRelatedPalette(ctName); + loadRelatedPalette(ctName); - assert(strstr(ctName, ".NEO")); + assert(strstr(ctName, ".NEO")); - Common::MemoryReadStream readS(ptr, 32); - - for (int i = 0; i < 16; i++) { - header[i] = readS.readUint16BE(); - } + Common::MemoryReadStream readS(ptr, 32); - gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200); + for (int i = 0; i < 16; i++) { + header[i] = readS.readUint16BE(); } + gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200); + free(dataPtr); return 0; } -void loadBgHigh(const char *currentPtr) { - memcpy(newPalette, currentPtr, 256 * 3); - currentPtr += 256 * 3; +byte loadCtOS(const char *ctName) { + byte *ptr, *dataPtr; - memcpy(page2Raw, currentPtr, 320 * 200); + if (currentCtName != ctName) + strcpy(currentCtName, ctName); + + ptr = dataPtr = readBundleFile(findFileInBundle(ctName)); - newColorMode = 2; - bgColorMode = 1; + uint16 bpp = READ_BE_UINT16(ptr); + ptr += 2; + + if (bpp == 8) { + memcpy(page3Raw, ptr + 256 * 3, 320 * 200); + renderer->loadCt256(ptr, ctName); + } else { + gfxConvertSpriteToRaw(page3Raw, ptr + 32, 160, 200); + renderer->loadCt16(ptr, ctName); + } + free(dataPtr); + return 0; } byte loadBg(const char *bgName) { byte *ptr, *dataPtr; - if (currentBgName[0] != bgName) - strcpy(currentBgName[0], bgName); - byte fileIdx = findFileInBundle(bgName); ptr = dataPtr = readBundleFile(fileIdx); - uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; + uint16 bpp = READ_BE_UINT16(ptr); + ptr += 2; + if (bpp == 8) { - loadBgHigh((const char *)ptr); + renderer->loadBg256(ptr, bgName); } else { - newColorMode = 1; - bgColorMode = 0; - - for (int i = 0; i < 16; i++) { - tempPalette[i] = READ_BE_UINT16(ptr); - ptr += 2; - } - if (g_cine->getGameType() == Cine::GType_FW) { loadRelatedPalette(bgName); } - gfxResetRawPage(page2Raw); - gfxConvertSpriteToRaw(page2Raw, ptr, 160, 200); + renderer->loadBg16(ptr, bgName); } free(dataPtr); return 0; @@ -127,28 +110,15 @@ byte loadBg(const char *bgName) { void addBackground(const char *bgName, uint16 bgIdx) { byte *ptr, *dataPtr; - strcpy(currentBgName[bgIdx], bgName); - byte fileIdx = findFileInBundle(bgName); ptr = dataPtr = readBundleFile(fileIdx); - additionalBgTable[bgIdx] = (byte *) malloc(320 * 200); - uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; if (bpp == 8) { - bgColorMode = 1; - memcpy(newPalette, ptr, 256 * 3); - ptr += 3 * 256; - memcpy(additionalBgTable[bgIdx], ptr, 320 * 200); + renderer->loadBg256(ptr, bgName, bgIdx); } else { - bgColorMode = 0; - for (int i = 0; i < 16; i++) { - tempPalette[i] = READ_BE_UINT16(ptr); - ptr += 2; - } - - gfxConvertSpriteToRaw(additionalBgTable[bgIdx], ptr, 160, 200); + renderer->loadBg16(ptr, bgName, bgIdx); } free(dataPtr); } diff --git a/engines/cine/bg.h b/engines/cine/bg.h index ca5c222131..5fa8209131 100644 --- a/engines/cine/bg.h +++ b/engines/cine/bg.h @@ -27,20 +27,9 @@ #define CINE_BG_H namespace Cine { -struct bgData { - byte *data; - byte colorMode; - byte *highPalette; - uint16 *lowPalette; -}; - byte loadBg(const char *bgName); -byte loadCt(const char *bgName); - -//extern bgData additionalBgTable[9]; -extern byte *additionalBgTable[9]; -extern byte currentAdditionalBgIdx; -extern byte currentAdditionalBgIdx2; +byte loadCtFW(const char *bgName); +byte loadCtOS(const char *bgName); void addBackground(const char *bgName, uint16 bgIdx); diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp index a70733dc68..cf25f1d355 100644 --- a/engines/cine/bg_list.cpp +++ b/engines/cine/bg_list.cpp @@ -40,62 +40,20 @@ Common::List<BGIncrust> bgIncrustList; /*! \brief Add masked sprite to the background * \param objIdx Sprite description - * \param addList Add sprite to incrust list if true - * \todo Fix incrust objects on CT background. Always drawing incrust elements - * on CT background breaks game zones */ -void addToBGList(int16 objIdx, bool addList) { - int16 x = objectTable[objIdx].x; - int16 y = objectTable[objIdx].y; - int16 width = animDataTable[objectTable[objIdx].frame]._var1; - int16 height = animDataTable[objectTable[objIdx].frame]._height; - const byte *data = animDataTable[objectTable[objIdx].frame].data(); - const byte *mask = animDataTable[objectTable[objIdx].frame].mask(); -// int16 part = objectTable[objIdx].part; - - // Operation Stealth may switch among multiple backgrounds - if (g_cine->getGameType() == GType_OS) { - for (int i = 0; i < 8; i++) { - if (additionalBgTable[i]) { - drawSpriteRaw2(data, objectTable[objIdx].part, width, height, additionalBgTable[i], x, y); - } - } - } else { - drawSpriteRaw(data, mask, width, height, page2Raw, x, y); - } +void addToBGList(int16 objIdx) { + renderer->incrustSprite(objectTable[objIdx]); - if (addList) - createBgIncrustListElement(objIdx, 0); + createBgIncrustListElement(objIdx, 0); } /*! \brief Add filled sprite to the background * \param objIdx Sprite description - * \param addList Add sprite to incrust list if true - * \todo Fix incrust objects on CT background. Always drawing incrust elements - * on CT background breaks game zones */ -void addSpriteFilledToBGList(int16 objIdx, bool addList) { - int16 x = objectTable[objIdx].x; - int16 y = objectTable[objIdx].y; - int16 width = animDataTable[objectTable[objIdx].frame]._realWidth; - int16 height = animDataTable[objectTable[objIdx].frame]._height; - const byte *data = animDataTable[objectTable[objIdx].frame].data(); - - if (data) { - // Operation Stealth may switch among multiple backgrounds - if (g_cine->getGameType() == GType_OS) { - for (int i = 0; i < 8; i++) { - if (additionalBgTable[i]) { - gfxFillSprite(data, width, height, additionalBgTable[i], x, y); - } - } - } else { - gfxFillSprite(data, width, height, page2Raw, x, y); - } - } +void addSpriteFilledToBGList(int16 objIdx) { + renderer->incrustMask(objectTable[objIdx]); - if (addList) - createBgIncrustListElement(objIdx, 1); + createBgIncrustListElement(objIdx, 1); } /*! \brief Add new element to incrust list @@ -115,7 +73,7 @@ void createBgIncrustListElement(int16 objIdx, int16 param) { bgIncrustList.push_back(tmp); } -/*! \brief Reset var8 (probably something related to bgIncrustList +/*! \brief Reset var8 (probably something related to bgIncrustList) */ void resetBgIncrustList(void) { var8 = 0; @@ -142,9 +100,9 @@ void loadBgIncrustFromSave(Common::InSaveFile &fHandle) { bgIncrustList.push_back(tmp); if (tmp.param == 0) { - addToBGList(tmp.objIdx, false); + renderer->incrustSprite(objectTable[tmp.objIdx]); } else { - addSpriteFilledToBGList(tmp.objIdx, false); + renderer->incrustMask(objectTable[tmp.objIdx]); } } } diff --git a/engines/cine/bg_list.h b/engines/cine/bg_list.h index 9ceae0acf5..1849d6ec3d 100644 --- a/engines/cine/bg_list.h +++ b/engines/cine/bg_list.h @@ -46,8 +46,8 @@ struct BGIncrust { extern Common::List<BGIncrust> bgIncrustList; extern uint32 var8; -void addToBGList(int16 objIdx, bool addList = true); -void addSpriteFilledToBGList(int16 idx, bool addList = true); +void addToBGList(int16 objIdx); +void addSpriteFilledToBGList(int16 idx); void createBgIncrustListElement(int16 objIdx, int16 param); void resetBgIncrustList(void); diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp index 41dd9be16f..efc33fadaf 100644 --- a/engines/cine/cine.cpp +++ b/engines/cine/cine.cpp @@ -95,7 +95,9 @@ int CineEngine::init() { int CineEngine::go() { CursorMan.showMouse(true); mainLoop(1); - gfxDestroy(); + + delete renderer; + delete[] page3Raw; delete g_sound; return 0; } @@ -105,8 +107,14 @@ void CineEngine::initialize() { setupOpcodes(); initLanguage(g_cine->getLanguage()); - gfxInit(); + if (g_cine->getGameType() == Cine::GType_OS) { + renderer = new OSRenderer; + } else { + renderer = new FWRenderer; + } + + page3Raw = new byte[320 * 200]; textDataPtr = (byte *)malloc(8000); partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer)); diff --git a/engines/cine/cine.h b/engines/cine/cine.h index 7ce5231446..710840c17e 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -64,7 +64,7 @@ enum CineGameFeatures { struct CINEGameDescription; -typedef Common::HashMap<Common::String, const char *, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo> StringPtrHashMap; +typedef Common::HashMap<Common::String, const char *> StringPtrHashMap; class CineEngine : public Engine { diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index 2730a92e62..47446f2410 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -27,6 +27,7 @@ #include "cine/bg.h" #include "cine/bg_list.h" #include "cine/various.h" +#include "cine/pal.h" #include "common/endian.h" #include "common/system.h" @@ -35,18 +36,8 @@ namespace Cine { -uint16 c_palette[256]; -byte colorMode256 = 0; -byte palette256[256 * 3]; -byte newPalette[256 * 3]; -byte newColorMode = 0; -byte ctColorMode = 0; -byte bgColorMode = 0; - -byte *screenBuffer; -byte *page1Raw; -byte *page2Raw; byte *page3Raw; +FWRenderer *renderer = NULL; static const byte mouseCursorNormal[] = { 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, @@ -96,28 +87,1197 @@ static const byte cursorPalette[] = { 0xff, 0xff, 0xff, 0xff }; -void gfxInit() { - screenBuffer = (byte *)malloc(320 * 200); - page1Raw = (byte *)malloc(320 * 200); - page2Raw = (byte *)malloc(320 * 200); - page3Raw = (byte *)malloc(320 * 200); - if (!screenBuffer || !page1Raw || !page2Raw || !page3Raw) { - error("Unable to allocate offscreen buffers"); +/*! \brief Initialize renderer + */ +FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""), + _cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]), + _activeLowPal(NULL), _changePal(0) { + + assert(_backBuffer); + + memset(_backBuffer, 0, _screenSize); + memset(_bgName, 0, sizeof (_bgName)); +} + +/* \brief Destroy renderer + */ +FWRenderer::~FWRenderer() { + delete[] _background; + delete[] _palette; + delete[] _backBuffer; + delete[] _activeLowPal; +} + +/* \brief Reset renderer state + */ +void FWRenderer::clear() { + delete[] _background; + delete[] _palette; + delete[] _activeLowPal; + + _background = NULL; + _palette = NULL; + _activeLowPal = NULL; + + memset(_backBuffer, 0, _screenSize); + + _cmd = ""; + _cmdY = 0; + _messageBg = 0; + _changePal = 0; +} + +/*! \brief Draw 1bpp sprite using selected color + * \param obj Object info + * \param fillColor Sprite color + */ +void FWRenderer::fillSprite(const objectStruct &obj, uint8 color) { + const byte *data = animDataTable[obj.frame].data(); + int x, y, width, height; + + x = obj.x; + y = obj.y; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + gfxFillSprite(data, width, height, _backBuffer, x, y, color); +} + +/*! \brief Draw 1bpp sprite using selected color on background + * \param obj Object info + * \param fillColor Sprite color + */ +void FWRenderer::incrustMask(const objectStruct &obj, uint8 color) { + const byte *data = animDataTable[obj.frame].data(); + int x, y, width, height; + + x = obj.x; + y = obj.y; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + gfxFillSprite(data, width, height, _background, x, y, color); +} + +/*! \brief Draw color sprite using with external mask + * \param obj Object info + * \param mask External mask + */ +void FWRenderer::drawMaskedSprite(const objectStruct &obj, const byte *mask) { + const byte *data = animDataTable[obj.frame].data(); + int x, y, width, height; + + x = obj.x; + y = obj.y; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + assert(mask); + + drawSpriteRaw(data, mask, width, height, _backBuffer, x, y); +} + +/*! \brief Draw color sprite + * \param obj Object info + */ +void FWRenderer::drawSprite(const objectStruct &obj) { + const byte *mask = animDataTable[obj.frame].mask(); + drawMaskedSprite(obj, mask); +} + +/*! \brief Draw color sprite on background + * \param obj Object info + */ +void FWRenderer::incrustSprite(const objectStruct &obj) { + const byte *data = animDataTable[obj.frame].data(); + const byte *mask = animDataTable[obj.frame].mask(); + int x, y, width, height; + + x = obj.x; + y = obj.y; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + assert(mask); + + drawSpriteRaw(data, mask, width, height, _background, x, y); +} + +/*! \brief Draw command box on screen + */ +void FWRenderer::drawCommand() { + unsigned int i; + int x = 10, y = _cmdY; + + drawPlainBox(x, y, 301, 11, 0); + drawBorder(x - 1, y - 1, 302, 12, 2); + + x += 2; + y += 2; + + for (i = 0; i < _cmd.size(); i++) { + x = drawChar(_cmd[i], x, y); + } +} + +/*! \brief Draw message in a box + * \param str Message to draw + * \param x Top left message box corner coordinate + * \param y Top left message box corner coordinate + * \param width Message box width + * \param color Message box background color + */ +void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte color) { + int i, tx, ty, tw; + int line = 0, words = 0, cw = 0; + int space = 0, extraSpace = 0; + + drawPlainBox(x, y, width, 4, color); + tx = x + 4; + ty = str[0] ? y - 5 : y + 4; + tw = width - 8; + + for (i = 0; str[i]; i++, line--) { + // Fit line of text into textbox + if (!line) { + while (str[i] == ' ') i++; + line = fitLine(str + i, tw, words, cw); + + if ( str[i + line] != '\0' && str[i + line] != 0x7C && words) { + space = (tw - cw) / words; + extraSpace = (tw - cw) % words; + } else { + space = 5; + extraSpace = 0; + } + + ty += 9; + drawPlainBox(x, ty, width, 9, color); + tx = x + 4; + } + + // draw characters + if (str[i] == ' ') { + tx += space + extraSpace; + + if (extraSpace) { + extraSpace = 0; + } + } else { + tx = drawChar(str[i], tx, ty); + } + } + + ty += 9; + drawPlainBox(x, ty, width, 4, color); + drawDoubleBorder(x, y, width, ty - y + 4, 2); +} + +/*! \brief Draw rectangle on screen + * \param x Top left corner coordinate + * \param y Top left corner coordinate + * \param width Rectangle width + * \param height Rectangle height + * \param color Fill color + */ +void FWRenderer::drawPlainBox(int x, int y, int width, int height, byte color) { + int i; + byte *dest = _backBuffer + y * 320 + x; + + if (width < 0) { + x += width; + width = -width; } - memset(page1Raw, 0, 320 * 200); - memset(page2Raw, 0, 320 * 200); - memset(page3Raw, 0, 320 * 200); - memset(additionalBgTable, 0, sizeof(additionalBgTable)); - additionalBgTable[0] = page2Raw; - additionalBgTable[8] = page3Raw; + if (height < 0) { + y += height; + height = -height; + } + + for (i = 0; i < height; i++) { + memset(dest + i * 320, color, width); + } +} + +/*! \brief Draw empty rectangle + * \param x Top left corner coordinate + * \param y Top left corner coordinate + * \param width Rectangle width + * \param height Rectangle height + * \param color Line color + */ +void FWRenderer::drawBorder(int x, int y, int width, int height, byte color) { + drawLine(x, y, width, 1, color); + drawLine(x, y + height, width, 1, color); + drawLine(x, y, 1, height, color); + drawLine(x + width, y, 1, height + 1, color); +} + +/*! \brief Draw empty 2 color rectangle (inner line color is black) + * \param x Top left corner coordinate + * \param y Top left corner coordinate + * \param width Rectangle width + * \param height Rectangle height + * \param color Outter line color + */ +void FWRenderer::drawDoubleBorder(int x, int y, int width, int height, byte color) { + drawBorder(x + 1, y + 1, width - 2, height - 2, 0); + drawBorder(x, y, width, height, color); +} + +/*! \brief Draw text character on screen + * \param character Character to draw + * \param x Character coordinate + * \param y Character coordinate + */ +int FWRenderer::drawChar(char character, int x, int y) { + int width, idx; + + if (character == ' ') { + x += 5; + } else if ((width = fontParamTable[(unsigned char)character].characterWidth)) { + idx = fontParamTable[(unsigned char)character].characterIdx; + drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y); + x += width + 1; + } + + return x; +} + +/*! \brief Draw Line + * \param x Line end coordinate + * \param y Line end coordinate + * \param width Horizontal line length + * \param height Vertical line length + * \param color Line color + * \note Either width or height must be equal to 1 + */ +void FWRenderer::drawLine(int x, int y, int width, int height, byte color) { + // this line is a special case of rectangle ;-) + drawPlainBox(x, y, width, height, color); +} + +/*! \brief Hide invisible parts of the sprite + * \param[in,out] mask Mask to be updated + * \param it Overlay info from overlayList + */ +void FWRenderer::remaskSprite(byte *mask, Common::List<overlay>::iterator it) { + AnimData &sprite = animDataTable[objectTable[it->objIdx].frame]; + int x, y, width, height, idx; + int mx, my, mw, mh; + + x = objectTable[it->objIdx].x; + y = objectTable[it->objIdx].y; + width = sprite._realWidth; + height = sprite._height; + + for (++it; it != overlayList.end(); ++it) { + if (it->type != 5) { + continue; + } + + idx = ABS(objectTable[it->objIdx].frame); + mx = objectTable[it->objIdx].x; + my = objectTable[it->objIdx].y; + mw = animDataTable[idx]._realWidth; + mh = animDataTable[idx]._height; + + gfxUpdateSpriteMask(mask, x, y, width, height, animDataTable[idx].data(), mx, my, mw, mh); + } +} + +/*! \brief Draw background to backbuffer + */ +void FWRenderer::drawBackground() { + assert(_background); + memcpy(_backBuffer, _background, _screenSize); +} + +/*! \brief Draw one overlay + * \param it Overlay info + */ +void FWRenderer::renderOverlay(const Common::List<overlay>::iterator &it) { + int idx, len, width; + objectStruct *obj; + AnimData *sprite; + byte *mask; + + switch (it->type) { + // color sprite + case 0: + sprite = animDataTable + objectTable[it->objIdx].frame; + len = sprite->_realWidth * sprite->_height; + mask = new byte[len]; + memcpy(mask, sprite->mask(), len); + remaskSprite(mask, it); + drawMaskedSprite(objectTable[it->objIdx], mask); + delete[] mask; + break; + + // game message + case 2: + if (it->objIdx >= messageTable.size()) { + return; + } + + _messageLen += messageTable[it->objIdx].size(); + drawMessage(messageTable[it->objIdx].c_str(), it->x, it->y, it->width, it->color); + break; + + // action failure message + case 3: + idx = it->objIdx * 4 + g_cine->_rnd.getRandomNumber(3); + len = strlen(failureMessages[idx]); + _messageLen += len; + width = 6 * len + 20; + width = width > 300 ? 300 : width; + + drawMessage(failureMessages[idx], (320 - width) / 2, 80, width, 4); + break; + + // bitmap + case 4: + assert(it->objIdx < NUM_MAX_OBJECT); + obj = objectTable + it->objIdx; + + if (obj->frame < 0) { + return; + } + + if (!animDataTable[obj->frame].data()) { + return; + } + + fillSprite(*obj); + break; + } } -void gfxDestroy() { - free(screenBuffer); - free(page1Raw); - free(page2Raw); - free(page3Raw); +/*! \brief Draw overlays + */ +void FWRenderer::drawOverlays() { + Common::List<overlay>::iterator it; + + for (it = overlayList.begin(); it != overlayList.end(); ++it) { + renderOverlay(it); + } +} + +/*! \brief Draw another frame + */ +void FWRenderer::drawFrame() { + drawBackground(); + drawOverlays(); + + if (!_cmd.empty()) { + drawCommand(); + } + + if (_changePal) { + refreshPalette(); + } + + blit(); +} + +/*! \brief Update screen + */ +void FWRenderer::blit() { + g_system->copyRectToScreen(_backBuffer, 320, 0, 0, 320, 200); +} + +/*! \brief Set player command string + * \param cmd New command string + */ +void FWRenderer::setCommand(const char *cmd) { + _cmd = cmd; +} + +/*! \brief Refresh current palette + */ +void FWRenderer::refreshPalette() { + int i; + byte pal[16*4]; + + assert(_activeLowPal); + + for (i = 0; i < 16; i++) { + // This seems to match the output from DOSbox. + pal[i * 4 + 2] = ((_activeLowPal[i] & 0x00f) >> 0) * 32; + pal[i * 4 + 1] = ((_activeLowPal[i] & 0x0f0) >> 4) * 32; + pal[i * 4 + 0] = ((_activeLowPal[i] & 0xf00) >> 8) * 32; + pal[i * 4 + 3] = 0; + } + + g_system->setPalette(pal, 0, 16); + _changePal = 0; +} + +/*! \brief Load palette of current background + */ +void FWRenderer::reloadPalette() { + assert(_palette); + + if (!_activeLowPal) { + _activeLowPal = new uint16[_lowPalSize]; + } + + assert(_activeLowPal); + + memcpy(_activeLowPal, _palette, _lowPalSize * sizeof (uint16)); + _changePal = 1; +} + +/*! \brief Load background into renderer + * \param bg Raw background data + */ +void FWRenderer::loadBg16(const byte *bg, const char *name) { + int i; + + if (!_background) { + _background = new byte[_screenSize]; + } + + if (!_palette) { + _palette = new uint16[_lowPalSize]; + } + + assert(_background && _palette); + + strcpy(_bgName, name); + + for (i = 0; i < _lowPalSize; i++, bg += 2) { + _palette[i] = READ_BE_UINT16(bg); + } + + gfxConvertSpriteToRaw(_background, bg, 160, 200); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::loadCt16(const byte *ct, const char *name) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::loadBg256(const byte *bg, const char *name) { + error("Future Wars renderer doesn't support 256 color mode"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::loadCt256(const byte *ct, const char *name) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::selectBg(unsigned int idx) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::selectScrollBg(unsigned int idx) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::setScroll(unsigned int shift) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +/*! \brief Placeholder for Operation Stealth implementation + */ +void FWRenderer::removeBg(unsigned int idx) { + error("Future Wars renderer doesn't support multiple backgrounds"); +} + +void FWRenderer::saveBg(Common::OutSaveFile &fHandle) { + fHandle.write(_bgName, 13); +} + +/*! \brief Restore active and backup palette from save + * \param fHandle Savefile open for reading + */ +void FWRenderer::restorePalette(Common::InSaveFile &fHandle) { + int i; + + if (!_palette) { + _palette = new uint16[_lowPalSize]; + } + + if (!_activeLowPal) { + _activeLowPal = new uint16[_lowPalSize]; + } + + assert(_palette && _activeLowPal); + + for (i = 0; i < _lowPalSize; i++) { + _activeLowPal[i] = fHandle.readUint16BE(); + } + + for (i = 0; i < _lowPalSize; i++) { + _palette[i] = fHandle.readUint16BE(); + } + + _changePal = 1; +} + +/*! \brief Write active and backup palette to save + * \param fHandle Savefile open for writing + */ +void FWRenderer::savePalette(Common::OutSaveFile &fHandle) { + int i; + + assert(_palette && _activeLowPal); + + for (i = 0; i < _lowPalSize; i++) { + fHandle.writeUint16BE(_activeLowPal[i]); + } + + for (i = 0; i < _lowPalSize; i++) { + fHandle.writeUint16BE(_palette[i]); + } +} + +/*! \brief Rotate active palette + * \param a First color to rotate + * \param b Last color to rotate + * \param c Possibly rotation step, must be equal to 1 at the moment + */ +void FWRenderer::rotatePalette(int a, int b, int c) { + palRotate(_activeLowPal, a, b, c); + refreshPalette(); +} + +/*! \brief Copy part of backup palette to active palette and transform + * \param first First color to transform + * \param last Last color to transform + * \param r Red channel transformation + * \param g Green channel transformation + * \param b Blue channel transformation + */ +void FWRenderer::transformPalette(int first, int last, int r, int g, int b) { + if (!_activeLowPal) { + _activeLowPal = new uint16[_lowPalSize]; + memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16)); + } + + transformPaletteRange(_activeLowPal, _palette, first, last, r, g, b); + refreshPalette(); +} + +/*! \brief Draw menu box, one item per line with possible highlight + * \param items Menu items + * \param height Item count + * \param x Top left menu corner coordinate + * \param y Top left menu corner coordinate + * \param width Menu box width + * \param selected Index of highlighted item (no highlight if less than 0) + */ +void FWRenderer::drawMenu(const CommandeType *items, unsigned int height, int x, int y, int width, int selected) { + int tx, ty, th = height * 9 + 10; + unsigned int i, j; + + if (x + width > 319) { + x = 319 - width; + } + + if (y + th > 199) { + y = 199 - th; + } + + drawPlainBox(x, y, width, 4, _messageBg); + + ty = y + 4; + + for (i = 0; i < height; i++, ty += 9) { + drawPlainBox(x, ty, width, 9, (int)i == selected ? 0 : _messageBg); + tx = x + 4; + + for (j = 0; items[i][j]; j++) { + tx = drawChar(items[i][j], tx, ty); + } + } + + drawPlainBox(x, ty, width, 4, _messageBg); + drawDoubleBorder(x, y, width, ty - y + 4, 2); +} + +/*! \brief Draw text input box + * \param info Input box message + * \param input Text entered in the input area + * \param cursor Cursor position in the input area + * \param x Top left input box corner coordinate + * \param y Top left input box corner coordinate + * \param width Input box width + */ +void FWRenderer::drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width) { + int i, tx, ty, tw; + int line = 0, words = 0, cw = 0; + int space = 0, extraSpace = 0; + + drawPlainBox(x, y, width, 4, _messageBg); + tx = x + 4; + ty = info[0] ? y - 5 : y + 4; + tw = width - 8; + + // input box info message + for (i = 0; info[i]; i++, line--) { + // fit line of text + if (!line) { + line = fitLine(info + i, tw, words, cw); + + if ( info[i + line] != '\0' && words) { + space = (tw - cw) / words; + extraSpace = (tw - cw) % words; + } else { + space = 5; + extraSpace = 0; + } + + ty += 9; + drawPlainBox(x, ty, width, 9, _messageBg); + tx = x + 4; + } + + // draw characters + if (info[i] == ' ') { + tx += space + extraSpace; + + if (extraSpace) { + extraSpace = 0; + } + } else { + tx = drawChar(info[i], tx, ty); + } + } + + // input area background + ty += 9; + drawPlainBox(x, ty, width, 9, _messageBg); + drawPlainBox(x + 16, ty - 1, width - 32, 9, 0); + tx = x + 20; + + // text in input area + for (i = 0; input[i]; i++) { + tx = drawChar(input[i], tx, ty); + + if (cursor == i + 2) { + drawLine(tx, ty - 1, 1, 9, 2); + } + } + + if (!input[0] || cursor == 1) { + drawLine(x + 20, ty - 1, 1, 9, 2); + } + + ty += 9; + drawPlainBox(x, ty, width, 4, _messageBg); + drawDoubleBorder(x, y, width, ty - y + 4, 2); +} + +/*! \brief Fade to black + */ +void FWRenderer::fadeToBlack() { + // FIXME: _activeLowPal is invalid when starting Operation Stealth + // Adding this sanity check fixes a crash when the game + // starts, but I'm not sure if this is the best place to check it + if (!_activeLowPal) { + warning("_activeLowPal is invalid"); + return; + } + + assert(_activeLowPal); + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 16; j++) { + _activeLowPal[j] = transformColor(_activeLowPal[j], -1, -1, -1); + } + + refreshPalette(); + g_system->updateScreen(); + g_system->delayMillis(50); + } +} + +/*! \brief Initialize Operation Stealth renderer + */ +OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0), + _bgShift(0) { + + int i; + for (i = 0; i < 9; i++) { + _bgTable[i].bg = NULL; + _bgTable[i].lowPal = NULL; + _bgTable[i].hiPal = NULL; + memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); + } +} + +/*! \brief Destroy Operation Stealth renderer + */ +OSRenderer::~OSRenderer() { + delete[] _activeHiPal; + + for (int i = 0; i < 9; i++) { + delete[] _bgTable[i].bg; + delete[] _bgTable[i].lowPal; + delete[] _bgTable[i].hiPal; + } +} + +/*! \brief Reset Operation Stealth renderer state + */ +void OSRenderer::clear() { + delete[] _activeHiPal; + _activeHiPal = NULL; + + for (int i = 0; i < 9; i++) { + delete[] _bgTable[i].bg; + delete[] _bgTable[i].lowPal; + delete[] _bgTable[i].hiPal; + + _bgTable[i].bg = NULL; + _bgTable[i].lowPal = NULL; + _bgTable[i].hiPal = NULL; + memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); + } + + _currentBg = 0; + _scrollBg = 0; + _bgShift = 0; + + FWRenderer::clear(); +} + +/*! \brief Draw 1bpp sprite using selected color on backgrounds + * \param obj Object info + * \param fillColor Sprite color + */ +void OSRenderer::incrustMask(const objectStruct &obj, uint8 color) { + const byte *data = animDataTable[obj.frame].data(); + int x, y, width, height, i; + + x = obj.x; + y = obj.y; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + for (i = 0; i < 8; i++) { + if (!_bgTable[i].bg) { + continue; + } + + gfxFillSprite(data, width, height, _bgTable[i].bg, x, y, color); + } +} + +/*! \brief Draw color sprite + * \param obj Object info + */ +void OSRenderer::drawSprite(const objectStruct &obj) { + const byte *data = animDataTable[obj.frame].data(); + int x, y, width, height, transColor; + + x = obj.x; + y = obj.y; + transColor = obj.part; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + drawSpriteRaw2(data, transColor, width, height, _backBuffer, x, y); +} + +/*! \brief Draw color sprite + * \param obj Object info + */ +void OSRenderer::incrustSprite(const objectStruct &obj) { + const byte *data = animDataTable[obj.frame].data(); + int x, y, width, height, transColor, i; + + x = obj.x; + y = obj.y; + transColor = obj.part; + width = animDataTable[obj.frame]._realWidth; + height = animDataTable[obj.frame]._height; + + for (i = 0; i < 8; i++) { + if (!_bgTable[i].bg) { + continue; + } + + drawSpriteRaw2(data, transColor, width, height, _bgTable[i].bg, x, y); + } +} + +/*! \brief Draw text character on screen + * \param character Character to draw + * \param x Character coordinate + * \param y Character coordinate + */ +int OSRenderer::drawChar(char character, int x, int y) { + int width, idx; + + if (character == ' ') { + x += 5; + } else if ((width = fontParamTable[(unsigned char)character].characterWidth)) { + idx = fontParamTable[(unsigned char)character].characterIdx; + drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y); + x += width + 1; + } + + return x; +} + +/*! \brief Draw background to backbuffer + */ +void OSRenderer::drawBackground() { + byte *main; + + main = _bgTable[_currentBg].bg; + assert(main); + + if (!_bgShift) { + memcpy(_backBuffer, main, _screenSize); + } else { + byte *scroll = _bgTable[_scrollBg].bg; + int mainShift = _bgShift * _screenWidth; + int mainSize = _screenSize - mainShift; + + assert(scroll); + + memcpy(_backBuffer, main + mainShift, mainSize); + memcpy(_backBuffer + mainSize, scroll, mainShift); + } +} + +/*! \brief Draw one overlay + * \param it Overlay info + */ +void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) { + int len; + objectStruct *obj; + AnimData *sprite; + byte *mask; + + switch (it->type) { + // color sprite + case 0: + sprite = animDataTable + objectTable[it->objIdx].frame; + len = sprite->_realWidth * sprite->_height; + mask = new byte[len]; + generateMask(sprite->data(), mask, len, objectTable[it->objIdx].part); + remaskSprite(mask, it); + drawMaskedSprite(objectTable[it->objIdx], mask); + delete[] mask; + break; + + // masked background + case 20: + assert(it->objIdx < NUM_MAX_OBJECT); + obj = objectTable + it->objIdx; + sprite = animDataTable + obj->frame; + + if (obj->frame < 0 || it->x > 8 || !_bgTable[it->x].bg || sprite->_bpp != 1) { + break; + } + + maskBgOverlay(_bgTable[it->x].bg, sprite->data(), sprite->_realWidth, sprite->_height, _backBuffer, obj->x, obj->y); + break; + + // something else + default: + FWRenderer::renderOverlay(it); + break; + } +} + +/*! \brief Refresh current palette + */ +void OSRenderer::refreshPalette() { + if (!_activeHiPal) { + FWRenderer::refreshPalette(); + return; + } + + int i; + byte pal[256*4]; + + for (i = 0; i < 256; i++) { + pal[i * 4 + 0] = _activeHiPal[i * 3 + 0]; + pal[i * 4 + 1] = _activeHiPal[i * 3 + 1]; + pal[i * 4 + 2] = _activeHiPal[i * 3 + 2]; + pal[i * 4 + 3] = 0; + } + + g_system->setPalette(pal, 0, 256); + _changePal = 0; +} + +/*! \brief Load palette of current background + */ +void OSRenderer::reloadPalette() { + // selected background in plane takeoff scene has swapped colors 12 + // and 14, shift background has it right + palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg]; + + assert(bg->lowPal || bg->hiPal); + + if (bg->lowPal) { + if (!_activeLowPal) { + _activeLowPal = new uint16[_lowPalSize]; + } + + assert(_activeLowPal); + + delete[] _activeHiPal; + _activeHiPal = NULL; + + memcpy(_activeLowPal, bg->lowPal, _lowPalSize * sizeof (uint16)); + } else { + if (!_activeHiPal) { + _activeHiPal = new byte[_hiPalSize]; + } + + assert(_activeHiPal); + + delete[] _activeLowPal; + _activeLowPal = NULL; + + memcpy(_activeHiPal, bg->hiPal, _hiPalSize); + } + _changePal = 1; +} + +/*! \brief Rotate active palette + * \param a First color to rotate + * \param b Last color to rotate + * \param c Possibly rotation step, must be equal to 1 at the moment + */ +void OSRenderer::rotatePalette(int a, int b, int c) { + if (_activeLowPal) { + FWRenderer::rotatePalette(a, b, c); + return; + } + + palRotate(_activeHiPal, a, b, c); + refreshPalette(); +} + +/*! \brief Copy part of backup palette to active palette and transform + * \param first First color to transform + * \param last Last color to transform + * \param r Red channel transformation + * \param g Green channel transformation + * \param b Blue channel transformation + */ +void OSRenderer::transformPalette(int first, int last, int r, int g, int b) { + palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg]; + + if (!bg->lowPal) { + if (!_activeHiPal) { + _activeHiPal = new byte[_hiPalSize]; + memset(_activeHiPal, 0, _hiPalSize); + } + + delete[] _activeLowPal; + _activeLowPal = NULL; + + transformPaletteRange(_activeHiPal, bg->hiPal, first, last, r, g, b); + } else { + if (!_activeLowPal) { + _activeLowPal = new uint16[_lowPalSize]; + memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16)); + } + + delete[] _activeHiPal; + _activeHiPal = NULL; + + transformPaletteRange(_activeLowPal, bg->lowPal, first, last, r, g, b); + } + + refreshPalette(); +} + +/*! \brief Load 16 color background into renderer + * \param bg Raw background data + * \param name Background filename + */ +void OSRenderer::loadBg16(const byte *bg, const char *name) { + loadBg16(bg, name, 0); +} + +/*! \brief Load 16 color background into renderer + * \param bg Raw background data + * \param name Background filename + * \param pos Background index + */ +void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { + int i; + assert(idx < 9); + + if (!_bgTable[idx].bg) { + _bgTable[idx].bg = new byte[_screenSize]; + } + + if (!_bgTable[idx].lowPal) { + _bgTable[idx].lowPal = new uint16[_lowPalSize]; + } + + assert(_bgTable[idx].bg && _bgTable[idx].lowPal); + + delete[] _bgTable[idx].hiPal; + _bgTable[idx].hiPal = NULL; + + strcpy(_bgTable[idx].name, name); + + for (i = 0; i < _lowPalSize; i++, bg += 2) { + _bgTable[idx].lowPal[i] = READ_BE_UINT16(bg); + } + + gfxConvertSpriteToRaw(_bgTable[idx].bg, bg, 160, 200); +} + +/*! \brief Load 16 color CT data as background into renderer + * \param ct Raw CT data + * \param name Background filename + */ +void OSRenderer::loadCt16(const byte *ct, const char *name) { + loadBg16(ct, name, 8); +} + +/*! \brief Load 256 color background into renderer + * \param bg Raw background data + * \param name Background filename + */ +void OSRenderer::loadBg256(const byte *bg, const char *name) { + loadBg256(bg, name, 0); +} + +/*! \brief Load 256 color background into renderer + * \param bg Raw background data + * \param name Background filename + * \param pos Background index + */ +void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) { + assert(idx < 9); + + if (!_bgTable[idx].bg) { + _bgTable[idx].bg = new byte[_screenSize]; + } + + if (!_bgTable[idx].hiPal) { + _bgTable[idx].hiPal = new byte[_hiPalSize]; + } + + assert(_bgTable[idx].bg && _bgTable[idx].hiPal); + + delete[] _bgTable[idx].lowPal; + _bgTable[idx].lowPal = NULL; + + strcpy(_bgTable[idx].name, name); + memcpy(_bgTable[idx].hiPal, bg, _hiPalSize); + memcpy(_bgTable[idx].bg, bg + _hiPalSize, _screenSize); +} + +/*! \brief Load 256 color CT data as background into renderer + * \param ct Raw CT data + * \param name Background filename + */ +void OSRenderer::loadCt256(const byte *ct, const char *name) { + loadBg256(ct, name, 8); +} + +/*! \brief Select active background and load its palette + * \param idx Background index + */ +void OSRenderer::selectBg(unsigned int idx) { + assert(idx < 9 && _bgTable[idx].bg); + assert(_bgTable[idx].lowPal || _bgTable[idx].hiPal); + + _currentBg = idx; + reloadPalette(); +} + +/*! \brief Select scroll background + * \param idx Scroll background index + */ +void OSRenderer::selectScrollBg(unsigned int idx) { + assert(idx < 9); + + if (_bgTable[idx].bg) { + _scrollBg = idx; + } + reloadPalette(); +} + +/*! \brief Set background scroll + * \param shift Background scroll in pixels + */ +void OSRenderer::setScroll(unsigned int shift) { + assert(shift <= 200); + + _bgShift = shift; +} + +/*! \brief Unload background from renderer + * \param idx Background to unload + */ +void OSRenderer::removeBg(unsigned int idx) { + assert(idx > 0 && idx < 9); + + if (_currentBg == idx) { + _currentBg = 0; + } + + if (_scrollBg == idx) { + _scrollBg = 0; + } + + delete[] _bgTable[idx].bg; + delete[] _bgTable[idx].lowPal; + delete[] _bgTable[idx].hiPal; + _bgTable[idx].bg = NULL; + _bgTable[idx].lowPal = NULL; + _bgTable[idx].hiPal = NULL; + memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name)); +} + +/*! \brief Fade to black + * \bug Operation Stealth sometimes seems to fade to black using + * transformPalette resulting in double fadeout + */ +void OSRenderer::fadeToBlack() { + if (!_activeHiPal) { + FWRenderer::fadeToBlack(); + return; + } + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < _hiPalSize; j++) { + _activeHiPal[j] = CLIP(_activeHiPal[j] - 32, 0, 255); + } + + refreshPalette(); + g_system->updateScreen(); + g_system->delayMillis(50); + } } void setMouseCursor(int cursor) { @@ -147,21 +1307,6 @@ void setMouseCursor(int cursor) { } } -static uint16 transformColor(uint16 baseColor, int8 r, int8 g, int8 b) { - int8 oriR = CLIP( (baseColor & 0x007) + r, 0, 7); - int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7); - int8 oriB = CLIP(((baseColor & 0x700) >> 8) + b, 0, 7); - - return oriR | (oriG << 4) | (oriB << 8); -} - -void transformPaletteRange(byte startColor, byte stopColor, int8 r, int8 g, int8 b) { - for (byte i = startColor; i <= stopColor; i++) { - c_palette[i] = transformColor(tempPalette[i], b, g, r); - } - //gfxFlipPage(page2); -} - void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) { int16 i, j; @@ -170,17 +1315,12 @@ void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *pag destPtr += i * 320; for (j = 0; j < width; j++) { - if (x + j >= 0 && x + j < 320 && i + y >= 0 - && i + y < 200) { - if (!*(spritePtr++)) { - *(destPtr++) = fillColor; - } else { - destPtr++; - } - } else { - destPtr++; - spritePtr++; + if (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200 && !*spritePtr) { + *destPtr = fillColor; } + + destPtr++; + spritePtr++; } } } @@ -360,53 +1500,7 @@ void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h) { } } -void gfxCopyRawPage(byte *source, byte *dest) { - memcpy(dest, source, 320 * 200); -} - -void gfxFlipRawPage(byte *frontBuffer) { - byte *page = frontBuffer; - int x, y, i; - byte *pixels = (byte *) screenBuffer; - byte c; - byte pal[256 * 4]; - - for (y = 0; y < 200; y++) { - for (x = 0; x < 320; x++) { - c = *(page++); - - if (!colorMode256) { - c = c & 15; - } - - pixels[x + 0 + y * 320] = c; - } - } - - if (colorMode256) { - for (i = 0; i < 256; i++) { - pal[i * 4 + 0] = palette256[i * 3 + 0]; - pal[i * 4 + 1] = palette256[i * 3 + 1]; - pal[i * 4 + 2] = palette256[i * 3 + 2]; - pal[i * 4 + 3] = 0; - } - g_system->setPalette(pal, 0, 256); - } else { - for (i = 0; i < 16; i++) { - // This seems to match the output from DOSbox. - pal[i * 4 + 2] = ((c_palette[i] & 0x00f) >> 0) * 32; - pal[i * 4 + 1] = ((c_palette[i] & 0x0f0) >> 4) * 32; - pal[i * 4 + 0] = ((c_palette[i] & 0xf00) >> 8) * 32; - pal[i * 4 + 3] = 0; - } - g_system->setPalette(pal, 0, 16); - } - - g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200); -} - -void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, - byte *page, int16 x, int16 y) { +void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y) { int16 i, j; // FIXME: Is it a bug if maskPtr == NULL? @@ -417,9 +1511,8 @@ void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int1 byte *destPtr = page + x + y * 320; destPtr += i * 320; - for (j = 0; j < width * 8; j++) { - if (((g_cine->getGameType() == Cine::GType_FW && (!maskPtr || !(*maskPtr))) || (g_cine->getGameType() == Cine::GType_OS)) && (x + j >= 0 - && x + j < 320 && i + y >= 0 && i + y < 200)) { + for (j = 0; j < width; j++) { + if ((!maskPtr || !(*maskPtr)) && x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200) { *(destPtr++) = *(spritePtr++); } else { destPtr++; @@ -432,21 +1525,19 @@ void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int1 } } -void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, - byte *page, int16 x, int16 y) { +void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y) { int16 i, j; for (i = 0; i < height; i++) { byte *destPtr = page + x + y * 320; destPtr += i * 320; - for (j = 0; j < width * 8; j++) { - if ((*(spritePtr) != transColor) && (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200)) { - *(destPtr++) = *(spritePtr++); - } else { - destPtr++; - spritePtr++; + for (j = 0; j < width; j++) { + if ((*spritePtr != transColor) && (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200)) { + *destPtr = *spritePtr; } + destPtr++; + spritePtr++; } } } @@ -499,93 +1590,4 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he } } -/*! \todo Fix rendering to prevent fadein artifacts - */ -void fadeFromBlack() { - int i, j; - int r, g, b, tr, tg, tb; - if (newColorMode == 2) { - colorMode256 = 1; - memset(palette256, 0, 256*3); - } else if (newColorMode == 1) { - colorMode256 = 0; - memset(c_palette, 0, 16 * sizeof(uint16)); - } - - for (i = 0; i < 8; i++ ) { - gfxFlipRawPage(page1Raw); - g_system->updateScreen(); - g_system->delayMillis(50); - - if (colorMode256) { - for (j = 0; j < 256*3; j++) { - r = palette256[j] + (newPalette[j] + 7) / 8; - palette256[j] = CLIP(r, 0, (int)newPalette[j]); - } - } else { - for (j = 0; j < 16; j++) { - r = c_palette[j] & 0xf; - g = (c_palette[j] & 0xf0) >> 4; - b = (c_palette[j] & 0xf00) >> 8; - - tr = tempPalette[j] & 0xf; - tg = (tempPalette[j] & 0xf0) >> 4; - tb = (tempPalette[j] & 0xf00) >> 8; - - r = CLIP(r + (tr + 7) / 8, 0, tr); - g = CLIP(g + (tg + 7) / 8, 0, tg); - b = CLIP(b + (tb + 7) / 8, 0, tb); - - c_palette[j] = r | (g << 4) | (b << 8); - } - - } - } - - if (colorMode256) { - memcpy(palette256, newPalette, 256*3); - } else { - memcpy(c_palette, tempPalette, sizeof(uint16) * 16); - } -} - -void fadeToBlack() { - for (int i = 0; i < 8; i++) { - if (colorMode256) { - for (int j = 0; j < 256*3; j++) { - palette256[j] = CLIP(palette256[j] - 32, 0, 255); - } - } else { - for (int j = 0; j < 16; j++) { - c_palette[j] = transformColor(c_palette[j], -1, -1, -1); - } - } - gfxFlipRawPage(page1Raw); - g_system->updateScreen(); - g_system->delayMillis(50); - } -} - -void blitRawScreen(byte *frontBuffer) { - gfxFlipRawPage(frontBuffer); -} - -void flip(void) { - blitRawScreen(page1Raw); - if (fadeRequired) { - if (newColorMode == 3) { - newColorMode = ctColorMode + 1; - } - - if (newColorMode == 2) { - colorMode256 = 1; - memcpy(palette256, newPalette, 256*3); - } else { - colorMode256 = 0; - memcpy(c_palette, tempPalette, sizeof(uint16) * 16); - } - fadeRequired = false; - } -} - } // End of namespace Cine diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index 3812b52113..c63c79ac82 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -26,24 +26,158 @@ #ifndef CINE_GFX_H #define CINE_GFX_H +#include "common/noncopyable.h" +#include "cine/object.h" + namespace Cine { +/*! \brief Background with palette + */ +struct palBg { + byte *bg; ///< Background data + byte *hiPal; ///< 256 color palette + uint16 *lowPal; ///< 16 color palette + char name[15]; ///< Background filename +}; + +/*! \brief Future Wars renderer + * + * Screen backbuffer is not cleared between frames, you can draw menus etc. + * without calling drawFrame() all the time + */ +class FWRenderer : public Common::NonCopyable { +private: + byte *_background; ///< Current background + char _bgName[13]; ///< Background filename + uint16 *_palette; ///< 16 color backup palette + + Common::String _cmd; ///< Player command string + +protected: + static const int _screenSize = 320 * 200; ///< Screen size + static const int _screenWidth = 320; ///< Screen width + static const int _screenHeight = 200; ///< Screen height + static const int _lowPalSize = 16; ///< 16 color palette size + + byte *_backBuffer; ///< Screen backbuffer + uint16 *_activeLowPal; ///< Active 16 color palette + int _changePal; ///< Load active palette to video backend on next frame + + void fillSprite(const objectStruct &obj, uint8 color = 0); + void drawMaskedSprite(const objectStruct &obj, const byte *mask); + virtual void drawSprite(const objectStruct &obj); + + void drawCommand(); + void drawMessage(const char *str, int x, int y, int width, byte color); + void drawPlainBox(int x, int y, int width, int height, byte color); + void drawBorder(int x, int y, int width, int height, byte color); + void drawDoubleBorder(int x, int y, int width, int height, byte color); + virtual int drawChar(char character, int x, int y); + void drawLine(int x, int y, int width, int height, byte color); + void remaskSprite(byte *mask, Common::List<overlay>::iterator it); + virtual void drawBackground(); + + virtual void renderOverlay(const Common::List<overlay>::iterator &it); + void drawOverlays(); + +public: + uint16 _messageBg; ///< Message box background color + uint16 _cmdY; ///< Player command string position on screen + + FWRenderer(); + virtual ~FWRenderer(); + + /*! \brief Test if renderer is ready to draw */ + virtual bool ready() { return _background != NULL; } + + virtual void clear(); + + void drawFrame(); + void blit(); + void setCommand(const char *cmd); + + virtual void incrustMask(const objectStruct &obj, uint8 color = 0); + virtual void incrustSprite(const objectStruct &obj); + + virtual void loadBg16(const byte *bg, const char *name); + virtual void loadBg16(const byte *bg, const char *name, unsigned int idx); + virtual void loadCt16(const byte *ct, const char *name); + virtual void loadBg256(const byte *bg, const char *name); + virtual void loadBg256(const byte *bg, const char *name, unsigned int idx); + virtual void loadCt256(const byte *ct, const char *name); + virtual void selectBg(unsigned int idx); + virtual void selectScrollBg(unsigned int idx); + virtual void setScroll(unsigned int shift); + virtual void removeBg(unsigned int idx); + void saveBg(Common::OutSaveFile &fHandle); + + virtual void refreshPalette(); + virtual void reloadPalette(); + void restorePalette(Common::InSaveFile &fHandle); + void savePalette(Common::OutSaveFile &fHandle); + virtual void rotatePalette(int a, int b, int c); + virtual void transformPalette(int first, int last, int r, int g, int b); + + void drawMenu(const CommandeType *items, unsigned int height, int x, int y, int width, int selected); + void drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width); + + virtual void fadeToBlack(); +}; + +/*! \brief Operation Stealth renderer + */ +class OSRenderer : public FWRenderer { +private: + palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer + byte *_activeHiPal; ///< Active 256 color palette + unsigned int _currentBg; ///< Current background + unsigned int _scrollBg; ///< Current scroll background + unsigned int _bgShift; ///< Background shift + +protected: + static const int _hiPalSize = 256 * 3; ///< 256 color palette size + + void drawSprite(const objectStruct &obj); + int drawChar(char character, int x, int y); + void drawBackground(); + void renderOverlay(const Common::List<overlay>::iterator &it); + +public: + OSRenderer(); + ~OSRenderer(); + + /*! \brief Test if renderer is ready to draw */ + bool ready() { return _bgTable[_currentBg].bg != NULL; } + + void clear(); + + void incrustMask(const objectStruct &obj, uint8 color = 0); + void incrustSprite(const objectStruct &obj); + + void loadBg16(const byte *bg, const char *name); + void loadBg16(const byte *bg, const char *name, unsigned int idx); + void loadCt16(const byte *ct, const char *name); + void loadBg256(const byte *bg, const char *name); + void loadBg256(const byte *bg, const char *name, unsigned int idx); + void loadCt256(const byte *ct, const char *name); + void selectBg(unsigned int idx); + void selectScrollBg(unsigned int idx); + void setScroll(unsigned int shift); + void removeBg(unsigned int idx); + + void refreshPalette(); + void reloadPalette(); + void rotatePalette(int a, int b, int c); + void transformPalette(int first, int last, int r, int g, int b); + + void fadeToBlack(); +}; + void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy); -extern byte *page1Raw; -extern byte *page2Raw; extern byte *page3Raw; +extern FWRenderer *renderer; -extern uint16 c_palette[256]; -extern byte colorMode256; -extern byte palette256[256 * 3]; -extern byte newPalette[256 * 3]; -extern byte newColorMode; -extern byte ctColorMode; -extern byte bgColorMode; - -void gfxInit(); -void gfxDestroy(); void setMouseCursor(int cursor); void gfxCopyPage(byte *source, byte *dest); diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index 6042849f59..cfb828cf3c 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -182,14 +182,12 @@ int getKeyData() { void CineEngine::mainLoop(int bootScriptIdx) { bool playerAction; uint16 quitFlag; - uint16 i; byte di; uint16 mouseButton; quitFlag = 0; if (_preLoad == false) { - resetSeqList(); resetBgIncrustList(); setTextWindow(0, 0, 20, 200); @@ -223,17 +221,10 @@ void CineEngine::mainLoop(int bootScriptIdx) { globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc. } - for (i = 0; i < 16; i++) { - c_palette[i] = 0; - } - - _paletteNeedUpdate = true; - strcpy(newPrcName, ""); strcpy(newRelName, ""); strcpy(newObjectName, ""); strcpy(newMsgName, ""); - strcpy(currentBgName[0], ""); strcpy(currentCtName, ""); strcpy(currentPartName, ""); @@ -257,8 +248,9 @@ void CineEngine::mainLoop(int bootScriptIdx) { setMouseCursor(MOUSE_CURSOR_CROSS); } - drawOverlays(); - flip(); + if (renderer->ready()) { + renderer->drawFrame(); + } if (waitForPlayerClick) { playerAction = false; @@ -289,6 +281,8 @@ void CineEngine::mainLoop(int bootScriptIdx) { } while (mouseButton != 0); waitForPlayerClick = 0; + + removeMessages(); } if (checkForPendingDataLoadSwitch) { diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp index 36f7b17a69..7666f05352 100644 --- a/engines/cine/object.cpp +++ b/engines/cine/object.cpp @@ -185,37 +185,37 @@ void addObjectParam(byte objIdx, byte paramIdx, int16 newValue) { } void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) { - paramIdx--; - - assert(paramIdx <= 5); + // Operation Stealth checks object index range, Future Wars doesn't. + if (g_cine->getGameType() == Cine::GType_OS && objIdx >= NUM_MAX_OBJECT) + return; switch (paramIdx) { - case 0: + case 1: objectTable[objIdx].x = newValue; break; - case 1: + case 2: objectTable[objIdx].y = newValue; break; - case 2: + case 3: objectTable[objIdx].mask = newValue; + // TODO: Check this part against disassembly if (removeOverlay(objIdx, 0)) { addOverlay(objIdx, 0); } break; - case 3: + case 4: objectTable[objIdx].frame = newValue; break; - case 4: - // is it really in Future Wars? it breaks the newspaper machine - // on the airport in Operation Stealth - if (newValue == -1 && g_cine->getGameType() != Cine::GType_OS) { + case 5: + // TODO: Test if this really breaks the newspaper machine on the airport in Operation Stealth. + if (g_cine->getGameType() == Cine::GType_FW && newValue == -1) { objectTable[objIdx].costume = globalVars[0]; } else { objectTable[objIdx].costume = newValue; } break; - case 5: + case 6: objectTable[objIdx].part = newValue; break; } @@ -236,6 +236,10 @@ uint16 compareObjectParam(byte objIdx, byte type, int16 value) { return compareResult; } +/*! \bug In Operation Stealth, if you try to go downstairs to the sea in the + * location between bank and hotel, getObjectParam is called with paramIdx 16 + * and crashes + */ int16 getObjectParam(uint16 objIdx, uint16 paramIdx) { assert(objIdx <= NUM_MAX_OBJECT); diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp index 9341563898..3e6f5adf40 100644 --- a/engines/cine/pal.cpp +++ b/engines/cine/pal.cpp @@ -28,8 +28,6 @@ namespace Cine { -uint16 tempPalette[256]; - uint16 palEntriesCount; PalEntry *palPtr = NULL; @@ -113,4 +111,64 @@ void loadRelatedPalette(const char *fileName) { } } +void palRotate(uint16 *pal, byte a, byte b, byte c) { + assert(pal); + + if (c == 1) { + uint16 currentColor = pal[b]; + + for (int i = b; i > a; i--) { + pal[i] = pal[i - 1]; + } + + pal[a] = currentColor; + } +} + +void palRotate(byte *pal, byte a, byte b, byte c) { + assert(pal); + + if (c == 1) { + byte currentR = pal[3 * b + 0]; + byte currentG = pal[3 * b + 1]; + byte currentB = pal[3 * b + 2]; + + for (int i = b; i > a; i--) { + pal[3 * i + 0] = pal[3 * (i - 1) + 0]; + pal[3 * i + 1] = pal[3 * (i - 1) + 1]; + pal[3 * i + 2] = pal[3 * (i - 1) + 2]; + } + + pal[3 * a + 0] = currentR; + pal[3 * a + 1] = currentG; + pal[3 * a + 2] = currentB; + } +} + +uint16 transformColor(uint16 baseColor, int r, int g, int b) { + int8 oriR = CLIP( (baseColor & 0x007) + b, 0, 7); + int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7); + int8 oriB = CLIP(((baseColor & 0x700) >> 8) + r, 0, 7); + + return oriR | (oriG << 4) | (oriB << 8); +} + +void transformPaletteRange(uint16 *dstPal, uint16 *srcPal, int startColor, int stopColor, int r, int g, int b) { + assert(srcPal && dstPal); + + for (int i = startColor; i <= stopColor; i++) { + dstPal[i] = transformColor(srcPal[i], r, g, b); + } +} + +void transformPaletteRange(byte *dstPal, byte *srcPal, int startColor, int stopColor, int r, int g, int b) { + assert(srcPal && dstPal); + + for (int i = startColor; i <= stopColor; i++) { + dstPal[3 * i + 0] = CLIP(srcPal[3 * i + 0] + r * 32, 0, 255); + dstPal[3 * i + 1] = CLIP(srcPal[3 * i + 1] + g * 32, 0, 255); + dstPal[3 * i + 2] = CLIP(srcPal[3 * i + 2] + b * 32, 0, 255); + } +} + } // End of namespace Cine diff --git a/engines/cine/pal.h b/engines/cine/pal.h index da822fa1a1..70fcc0d98a 100644 --- a/engines/cine/pal.h +++ b/engines/cine/pal.h @@ -36,10 +36,14 @@ struct PalEntry { void loadPal(const char *fileName); -extern uint16 tempPalette[256]; - void loadRelatedPalette(const char *fileName); +void palRotate(uint16 *pal, byte a, byte b, byte c); +void palRotate(byte *pal, byte a, byte b, byte c); +uint16 transformColor(uint16 baseColor, int r, int g, int b); +void transformPaletteRange(uint16 *srcPal, uint16 *dstPal, int startColor, int stopColor, int r, int g, int b); +void transformPaletteRange(byte *srcPal, byte *dstPal, int startColor, int stopColor, int r, int g, int b); + } // End of namespace Cine #endif diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp index 43656460c5..b39f1eff7d 100644 --- a/engines/cine/part.cpp +++ b/engines/cine/part.cpp @@ -70,25 +70,41 @@ void closePart(void) { // TODO } -static void fixVolCnfFileName(char *dst, const uint8 *src) { - memcpy(dst, src, 8); - src += 8; - dst[8] = 0; - - char *ext = strchr(dst, ' '); - if (!ext) { - ext = &dst[8]; - } - if (*src == ' ') { - *ext = 0; - } else { - *ext++ = '.'; - memcpy(ext, src, 3); - char *end = strchr(ext, ' '); - if (!end) { - end = &ext[3]; +static Common::String fixVolCnfFileName(const uint8 *src, uint len) { + assert(len == 11 || len == 13); + // Copy source to a temporary buffer and force a trailing zero for string manipulation + char tmp[14]; + memcpy(tmp, src, len); + tmp[len] = 0; + + if (len == 11) { + // Filenames of length 11 have no separation of the extension and the basename + // so that's why we have to convert them first. There's no trailing zero in them + // either and they're always of the full length 11 with padding spaces. Extension + // can be always found at offset 8 onwards. + // + // Examples of filename mappings: + // "AEROPORTMSG" -> "AEROPORT.MSG" + // "MITRAILLHP " -> "MITRAILL.HP" (Notice the trailing space after the extension) + // "BOND10 " -> "BOND10" + // "GIRL SET" -> "GIRL.SET" + + // Replace all space characters with zeroes + for (uint i = 0; i < len; i++) + if (tmp[i] == ' ') + tmp[i] = 0; + // Extract the filename's extension + Common::String extension(tmp + 8); + tmp[8] = 0; // Force separation of extension and basename + Common::String basename(tmp); + if (extension.empty()) { + return basename; + } else { + return basename + "." + extension; } - *end = 0; + } else { + // Filenames of length 13 are okay as they are, no need for conversion + return Common::String(tmp); } } @@ -97,30 +113,25 @@ void CineEngine::readVolCnf() { if (!f.open("vol.cnf")) { error("Unable to open 'vol.cnf'"); } - bool abaseHeader = false; uint32 unpackedSize, packedSize; char hdr[8]; f.read(hdr, 8); - if (memcmp(hdr, "ABASECP", 7) == 0) { - abaseHeader = true; + bool compressed = (memcmp(hdr, "ABASECP", 7) == 0); + if (compressed) { unpackedSize = f.readUint32BE(); packedSize = f.readUint32BE(); } else { f.seek(0); unpackedSize = packedSize = f.size(); } - uint8 *buf = (uint8 *)malloc(unpackedSize); - if (!buf) { - error("Unable to allocate %d bytes", unpackedSize); - } + uint8 *buf = new uint8[unpackedSize]; f.read(buf, packedSize); if (packedSize != unpackedSize) { - bool b = delphineUnpack(buf, buf, packedSize); - if (!b) { + CineUnpacker cineUnpacker; + if (!cineUnpacker.unpack(buf, packedSize, buf, unpackedSize)) { error("Error while unpacking 'vol.cnf' data"); } } - const int fileNameLength = abaseHeader ? 11 : 13; uint8 *p = buf; int resourceFilesCount = READ_BE_UINT16(p); p += 2; int entrySize = READ_BE_UINT16(p); p += 2; @@ -132,31 +143,48 @@ void CineEngine::readVolCnf() { p += entrySize; } - int volumeEntriesCount = 0; + // Check file name blocks' sizes + bool fileNameLenMod11, fileNameLenMod13; + fileNameLenMod11 = fileNameLenMod13 = true; for (int i = 0; i < resourceFilesCount; ++i) { int size = READ_BE_UINT32(p); p += 4; - assert((size % fileNameLength) == 0); - volumeEntriesCount += size / fileNameLength; + fileNameLenMod11 &= ((size % 11) == 0); + fileNameLenMod13 &= ((size % 13) == 0); p += size; } + // Make sure at least one of the candidates for file name length fits the data + assert(fileNameLenMod11 || fileNameLenMod13); + + // File name length used to be deduced from the fact whether the file + // was compressed or not. Compressed files used file name length 11, + // uncompressed files used file name length 13. It worked almost always, + // but not with the game entry that's detected as the Operation Stealth's + // US Amiga release. It uses a compressed 'vol.cnf' file but still uses + // file names of length 13. So we try to deduce the file name length from + // the data in the 'vol.cnf' file. + int fileNameLength; + if (fileNameLenMod11 != fileNameLenMod13) { + // All file name blocks' sizes were divisible by either 11 or 13, but not with both. + fileNameLength = (fileNameLenMod11 ? 11 : 13); + } else { + warning("Couldn't deduce file name length from data in 'vol.cnf', using a backup deduction scheme."); + // Here we use the former file name length detection method + // if we couldn't deduce the file name length from the data. + fileNameLength = (compressed ? 11 : 13); + } p = buf + 4 + resourceFilesCount * entrySize; for (int i = 0; i < resourceFilesCount; ++i) { int count = READ_BE_UINT32(p) / fileNameLength; p += 4; while (count--) { - char volumeEntryName[13]; - if (abaseHeader) { - fixVolCnfFileName(volumeEntryName, p); - } else { - memcpy(volumeEntryName, p, fileNameLength); - } + Common::String volumeEntryName = fixVolCnfFileName(p, fileNameLength); _volumeEntriesMap.setVal(volumeEntryName, _volumeResourceFiles[i].c_str()); - debugC(5, kCineDebugPart, "Added volume entry name '%s' resource file '%s'", volumeEntryName, _volumeResourceFiles[i].c_str()); + debugC(5, kCineDebugPart, "Added volume entry name '%s' resource file '%s'", volumeEntryName.c_str(), _volumeResourceFiles[i].c_str()); p += fileNameLength; } } - free(buf); + delete[] buf; } int16 findFileInBundle(const char *fileName) { @@ -197,7 +225,10 @@ byte *readBundleFile(int16 foundFileIdx) { if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) { byte *unpackBuffer = (byte *)malloc(partBuffer[foundFileIdx].packedSize); readFromPart(foundFileIdx, unpackBuffer); - delphineUnpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize); + CineUnpacker cineUnpacker; + if (!cineUnpacker.unpack(unpackBuffer, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize)) { + warning("Error unpacking '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName); + } free(unpackBuffer); } else { readFromPart(foundFileIdx, dataPtr); diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp index 0f068a197e..402c97b1a6 100644 --- a/engines/cine/prc.cpp +++ b/engines/cine/prc.cpp @@ -98,10 +98,10 @@ void loadPrc(const char *pPrcName) { char buffer[256]; for (s = 0; s < numScripts; s++) { - if (scriptTable[s].size) { + if (scriptTable[s]->_size) { sprintf(buffer, "%s_%03d.txt", pPrcName, s); - decompileScript(scriptTable[s].ptr, scriptTable[s].stack, scriptTable[s].size, s); + decompileScript((const byte *)scriptTable[s]->getString(0), scriptTable[s]->_size, s); dumpScript(buffer); } } diff --git a/engines/cine/rel.cpp b/engines/cine/rel.cpp index f550efed27..dd2d0f68b6 100644 --- a/engines/cine/rel.cpp +++ b/engines/cine/rel.cpp @@ -81,10 +81,10 @@ void loadRel(char *pRelName) { char buffer[256]; for (s = 0; s < numEntry; s++) { - if (relTable[s].size) { + if (relTable[s]->_size) { sprintf(buffer, "%s_%03d.txt", pRelName, s); - decompileScript(relTable[s].data, NULL, relTable[s].size, s); + decompileScript((const byte *)relTable[s]->getString(0), relTable[s]->_size, s); dumpScript(buffer); } } diff --git a/engines/cine/script.h b/engines/cine/script.h index 4a2e7072ee..eeac0e8809 100644 --- a/engines/cine/script.h +++ b/engines/cine/script.h @@ -155,8 +155,8 @@ protected: int o1_getObjectParam(); int o1_addObjectParam(); int o1_subObjectParam(); - int o1_add2ObjectParam(); - int o1_sub2ObjectParam(); + int o1_mulObjectParam(); + int o1_divObjectParam(); int o1_compareObjectParam(); int o1_setupObject(); int o1_checkCollision(); @@ -230,6 +230,7 @@ protected: int o1_unloadMask5(); // pointers to member functions in C++ suck... + int o2_loadCt(); int o2_loadPart(); int o2_addSeqListElement(); int o2_removeSeq(); @@ -362,7 +363,7 @@ extern ScriptVars globalVars; void setupOpcodes(); -void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx); +void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx); void dumpScript(char *dumpName); #define OP_loadPart 0x3F diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index f833d7c30b..845120c99e 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -41,11 +41,6 @@ namespace Cine { ScriptVars globalVars(NUM_MAX_VAR); uint16 compareVars(int16 a, int16 b); -void palRotate(byte a, byte b, byte c); -void removeSeq(uint16 param1, uint16 param2, uint16 param3); -uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3); -void addGfxElementA0(int16 param1, int16 param2); -void removeGfxElementA0(int16 idx, int16 param); const Opcode FWScript::_opcodeTable[] = { /* 00 */ @@ -54,8 +49,8 @@ const Opcode FWScript::_opcodeTable[] = { { &FWScript::o1_addObjectParam, "bbw" }, { &FWScript::o1_subObjectParam, "bbw" }, /* 04 */ - { &FWScript::o1_add2ObjectParam, "bbw" }, - { &FWScript::o1_sub2ObjectParam, "bbw" }, + { &FWScript::o1_mulObjectParam, "bbw" }, + { &FWScript::o1_divObjectParam, "bbw" }, { &FWScript::o1_compareObjectParam, "bbw" }, { &FWScript::o1_setupObject, "bwwww" }, /* 08 */ @@ -808,23 +803,32 @@ int FWScript::o1_subObjectParam() { return 0; } -/*! \todo Implement this instruction - */ -int FWScript::o1_add2ObjectParam() { - uint16 a = getNextByte(); - uint16 b = getNextByte(); - uint16 c = getNextWord(); - warning("STUB: o1_add2ObjectParam(%x, %x, %x)", a, b, c); +int FWScript::o1_mulObjectParam() { + byte objIdx = getNextByte(); + byte paramIdx = getNextByte(); + int16 newValue = getNextWord(); + + debugC(5, kCineDebugScript, "Line: %d: mulObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); + + // FIXME? In PC versions of Future Wars and Operation Stealth the multiplication is done unsigned. + // (16b x 16b -> 32b, taking only 16 LSBs). The question is, does it really matter? + int16 currentValue = getObjectParam(objIdx, paramIdx); + modifyObjectParam(objIdx, paramIdx, currentValue * newValue); return 0; } -/*! \todo Implement this instruction - */ -int FWScript::o1_sub2ObjectParam() { - uint16 a = getNextByte(); - uint16 b = getNextByte(); - uint16 c = getNextWord(); - warning("STUB: o1_sub2ObjectParam(%x, %x, %x)", a, b, c); +int FWScript::o1_divObjectParam() { + byte objIdx = getNextByte(); + byte paramIdx = getNextByte(); + int16 newValue = getNextWord(); + + debugC(5, kCineDebugScript, "Line: %d: divObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); + + // In PC versions of Future Wars and Operation Stealth the division is done signed. + // Dividend is first sign extended from 16 bits to 32 bits and then divided by the + // 16 bit divider using signed division. Only 16 LSBs of the quotient are saved. + int16 currentValue = getObjectParam(objIdx, paramIdx); + modifyObjectParam(objIdx, paramIdx, currentValue / newValue); return 0; } @@ -1299,7 +1303,7 @@ int FWScript::o1_loadCt() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param); - loadCt(param); + loadCtFW(param); return 0; } @@ -1355,31 +1359,29 @@ int FWScript::o1_blitAndFade() { debugC(5, kCineDebugScript, "Line: %d: request fadein", _line); // TODO: use real code - drawOverlays(); - fadeRequired = true; - flip(); - // fadeFromBlack(); + + renderer->reloadPalette(); return 0; } int FWScript::o1_fadeToBlack() { debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line); - fadeToBlack(); + renderer->fadeToBlack(); return 0; } int FWScript::o1_transformPaletteRange() { byte startColor = getNextByte(); byte numColor = getNextByte(); - uint16 r = getNextWord(); - uint16 g = getNextWord(); - uint16 b = getNextWord(); + int16 r = getNextWord(); + int16 g = getNextWord(); + int16 b = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b); - transformPaletteRange(startColor, numColor, r, g, b); + renderer->transformPalette(startColor, numColor, r, g, b); return 0; } @@ -1387,7 +1389,8 @@ int FWScript::o1_setDefaultMenuColor2() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param); - defaultMenuBoxColor2 = param; + + renderer->_messageBg = param; return 0; } @@ -1397,7 +1400,8 @@ int FWScript::o1_palRotate() { byte c = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c); - palRotate(a, b, c); + + renderer->rotatePalette(a, b, c); return 0; } @@ -1475,11 +1479,7 @@ int FWScript::o1_compareGlobalVar() { debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value); - if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix - _compare = 1; - } else { - _compare = compareVars(_globalVars[varIdx], value); - } + _compare = compareVars(_globalVars[varIdx], value); } return 0; @@ -1558,7 +1558,8 @@ int FWScript::o1_setDefaultMenuColor() { byte param = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param); - defaultMenuBoxColor = param; + + renderer->_cmdY = param; return 0; } @@ -1608,7 +1609,8 @@ int FWScript::o1_stopSample() { return 0; } -/*! \todo Implement this instruction +/*! \todo Implement this instruction's Amiga part (PC part already done) + * In PC versions of Future Wars and Operation Stealth this instruction does nothing else but read the parameters. */ int FWScript::o1_op71() { byte a = getNextByte(); @@ -1617,7 +1619,8 @@ int FWScript::o1_op71() { return 0; } -/*! \todo Implement this instruction +/*! \todo Implement this instruction's Amiga part (PC part already done) + * In PC versions of Future Wars and Operation Stealth this instruction does nothing else but read the parameters. */ int FWScript::o1_op72() { uint16 a = getNextWord(); @@ -1627,7 +1630,8 @@ int FWScript::o1_op72() { return 0; } -/*! \todo Implement this instruction +/*! \todo Implement this instruction's Amiga part (PC part already done) + * In PC versions of Future Wars and Operation Stealth this instruction does nothing else but read the parameters. */ int FWScript::o1_op73() { // I believe this opcode is identical to o1_op72(). In fact, Operation @@ -1635,7 +1639,7 @@ int FWScript::o1_op73() { uint16 a = getNextWord(); byte b = getNextByte(); uint16 c = getNextWord(); - warning("STUB: o1_op72(%x, %x, %x)", a, b, c); + warning("STUB: o1_op73(%x, %x, %x)", a, b, c); return 0; } @@ -1728,18 +1732,6 @@ int FWScript::o1_unloadMask5() { //----------------------------------------------------------------------- -void palRotate(byte a, byte b, byte c) { - if (c == 1) { - uint16 currentColor = c_palette[b]; - - for (int16 i = b; i > a; i--) { - c_palette[i] = c_palette[i - 1]; - } - - c_palette[a] = currentColor; - } -} - void addScriptToList0(uint16 idx) { ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx)); assert(tmp); @@ -1863,14 +1855,13 @@ const char *getObjPramName(byte paramIdx) { } } -void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx) { +void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx) { char lineBuffer[256]; - byte *localScriptPtr = scriptPtr; + const byte *localScriptPtr = scriptPtr; uint16 exitScript; uint32 position = 0; assert(scriptPtr); - // assert(stackPtr); exitScript = 0; @@ -2292,7 +2283,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position); } - position += strlen((char *)localScriptPtr + position) + 1; + position += strlen((const char *)localScriptPtr + position) + 1; break; } case 0x40: @@ -2309,7 +2300,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position); - position += strlen((char *)localScriptPtr + position) + 1; + position += strlen((const char *)localScriptPtr + position) + 1; break; } case OP_requestCheckPendingDataLoad: // nop @@ -2461,7 +2452,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 { sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position); - position += strlen((char *)localScriptPtr + position); + position += strlen((const char *)localScriptPtr + position); break; } case 0x5A: @@ -2540,7 +2531,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 { sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position); - position += strlen((char *)localScriptPtr + position) + 1; + position += strlen((const char *)localScriptPtr + position) + 1; break; } case 0x6E: // nop @@ -2801,7 +2792,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position); - position += strlen((char *)localScriptPtr + position); + position += strlen((const char *)localScriptPtr + position); break; } @@ -2825,7 +2816,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position); - position += strlen((char *)localScriptPtr + position); + position += strlen((const char *)localScriptPtr + position); break; } diff --git a/engines/cine/script_os.cpp b/engines/cine/script_os.cpp index 1f5ea2b838..319fca5d3c 100644 --- a/engines/cine/script_os.cpp +++ b/engines/cine/script_os.cpp @@ -45,8 +45,8 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o1_addObjectParam, "bbw" }, { &FWScript::o1_subObjectParam, "bbw" }, /* 04 */ - { &FWScript::o1_add2ObjectParam, "bbw" }, - { &FWScript::o1_sub2ObjectParam, "bbw" }, + { &FWScript::o1_mulObjectParam, "bbw" }, + { &FWScript::o1_divObjectParam, "bbw" }, { &FWScript::o1_compareObjectParam, "bbw" }, { &FWScript::o1_setupObject, "bwwww" }, /* 08 */ @@ -73,7 +73,7 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o1_loadMask4, "b" }, { &FWScript::o1_unloadMask4, "b" }, { &FWScript::o1_addSpriteFilledToBgList, "b" }, - { &FWScript::o1_op1B, "" }, + { &FWScript::o1_op1B, "" }, /* TODO: Name this opcode properly. */ /* 1C */ { 0, 0 }, { &FWScript::o1_label, "l" }, @@ -116,7 +116,7 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o1_loadAnim, "s" }, /* 3C */ { &FWScript::o1_loadBg, "s" }, - { &FWScript::o1_loadCt, "s" }, + { &FWScript::o2_loadCt, "s" }, { 0, 0 }, { &FWScript::o2_loadPart, "s" }, /* 40 */ @@ -173,7 +173,7 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o1_setDefaultMenuColor, "b" }, { &FWScript::o1_allowPlayerInput, "" }, { &FWScript::o1_disallowPlayerInput, "" }, - { &FWScript::o1_changeDataDisk, "b" }, + { &FWScript::o1_changeDataDisk, "b" }, /* Same as opcodes 0x95 and 0xA9. */ /* 6C */ { 0, 0 }, { &FWScript::o1_loadMusic, "s" }, @@ -181,9 +181,9 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o1_fadeOutMusic, "" }, /* 70 */ { &FWScript::o1_stopSample, "" }, - { &FWScript::o1_op71, "bw" }, - { &FWScript::o1_op72, "wbw" }, - { &FWScript::o1_op72, "wbw" }, + { &FWScript::o1_op71, "bw" }, /* TODO: Name this opcode properly. */ + { &FWScript::o1_op72, "wbw" }, /* Same as opcode 0x73. TODO: Name this opcode properly. */ + { &FWScript::o1_op72, "wbw" }, /* Same as opcode 0x72. */ /* 74 */ { 0, 0 }, { 0, 0 }, @@ -193,7 +193,7 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o2_playSampleAlt, "bbwbww" }, { &FWScript::o1_disableSystemMenu, "b" }, { &FWScript::o1_loadMask5, "b" }, - { &FWScript::o1_unloadMask5, "b" }, + { &FWScript::o1_unloadMask5, "b" }, /* Last opcode used by Future Wars. */ /* 7C */ { 0, 0 }, { 0, 0 }, @@ -201,8 +201,8 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o2_addSeqListElement, "bbbbwww" }, /* 80 */ { &FWScript::o2_removeSeq, "bb" }, - { &FWScript::o2_op81, "" }, - { &FWScript::o2_op82, "bbw" }, + { &FWScript::o2_op81, "" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_op82, "bbwwb" }, /* TODO: Name this opcode properly. */ { &FWScript::o2_isSeqRunning, "bb" }, /* 84 */ { &FWScript::o2_gotoIfSupNearest, "b" }, @@ -216,7 +216,7 @@ const Opcode OSScript::_opcodeTable[] = { { &FWScript::o2_startObjectScript, "b" }, /* 8C */ { &FWScript::o2_stopObjectScript, "b" }, - { &FWScript::o2_op8D, "wwwwwwww" }, + { &FWScript::o2_op8D, "wwwwwwww" }, /* TODO: Name this opcode properly. */ { &FWScript::o2_addBackground, "bs" }, { &FWScript::o2_removeBackground, "b" }, /* 90 */ @@ -226,32 +226,32 @@ const Opcode OSScript::_opcodeTable[] = { { 0, 0 }, /* 94 */ { 0, 0 }, - { &FWScript::o1_changeDataDisk, "b" }, + { &FWScript::o1_changeDataDisk, "b" }, /* Same as opcodes 0x6B and 0xA9. */ { 0, 0 }, { 0, 0 }, /* 98 */ { 0, 0 }, { 0, 0 }, - { &FWScript::o2_wasZoneChecked, "" }, - { &FWScript::o2_op9B, "wwwwwwww" }, + { &FWScript::o2_wasZoneChecked, "b" }, + { &FWScript::o2_op9B, "wwwwwwww" }, /* TODO: Name this opcode properly. */ /* 9C */ - { &FWScript::o2_op9C, "wwww" }, + { &FWScript::o2_op9C, "wwww" }, /* TODO: Name this opcode properly. */ { &FWScript::o2_useBgScroll, "b" }, { &FWScript::o2_setAdditionalBgVScroll, "c" }, - { &FWScript::o2_op9F, "ww" }, + { &FWScript::o2_op9F, "ww" }, /* TODO: Name this opcode properly. */ /* A0 */ - { &FWScript::o2_addGfxElementA0, "ww" }, - { &FWScript::o2_removeGfxElementA0, "ww" }, - { &FWScript::o2_opA2, "ww" }, - { &FWScript::o2_opA3, "ww" }, + { &FWScript::o2_addGfxElementA0, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_removeGfxElementA0, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_opA2, "ww" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_opA3, "ww" }, /* TODO: Name this opcode properly. */ /* A4 */ - { &FWScript::o2_loadMask22, "b" }, - { &FWScript::o2_unloadMask22, "b" }, + { &FWScript::o2_loadMask22, "b" }, /* TODO: Name this opcode properly. */ + { &FWScript::o2_unloadMask22, "b" }, /* TODO: Name this opcode properly. */ { 0, 0 }, { 0, 0 }, /* A8 */ { 0, 0 }, - { &FWScript::o1_changeDataDisk, "b" } + { &FWScript::o1_changeDataDisk, "b" } /* Same as opcodes 0x6B and 0x95. */ }; const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable); @@ -365,6 +365,14 @@ FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const // OPERATION STEALTH opcodes // ------------------------------------------------------------------------ +int FWScript::o2_loadCt() { + const char *param = getNextString(); + + debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param); + loadCtOS(param); + return 0; +} + int FWScript::o2_loadPart() { const char *param = getNextString(); @@ -447,7 +455,9 @@ int FWScript::o2_op82() { byte a = getNextByte(); byte b = getNextByte(); uint16 c = getNextWord(); - warning("STUB: o2_op82(%x, %x, %x)", a, b, c); + uint16 d = getNextWord(); + byte e = getNextByte(); + warning("STUB: o2_op82(%x, %x, %x, %x, %x)", a, b, c, d, e); return 0; } @@ -615,20 +625,7 @@ int FWScript::o2_removeBackground() { debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param); - if (additionalBgTable[param]) { - free(additionalBgTable[param]); - additionalBgTable[param] = NULL; - } - - if (currentAdditionalBgIdx == param) { - currentAdditionalBgIdx = 0; - } - - if (currentAdditionalBgIdx2 == param) { - currentAdditionalBgIdx2 = 0; - } - - strcpy(currentBgName[param], ""); + renderer->removeBg(param); return 0; } @@ -644,29 +641,20 @@ int FWScript::o2_loadAbs() { int FWScript::o2_loadBg() { byte param = getNextByte(); - assert(param <= 8); + assert(param < 9); debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param); - if (additionalBgTable[param]) { - currentAdditionalBgIdx = param; - if (param == 8) { - newColorMode = 3; - } else { - newColorMode = bgColorMode + 1; - } - //if (_screenNeedFadeOut == 0) { - // adBgVar1 = 1; - //} - fadeRequired = true; - } + renderer->selectBg(param); return 0; } -/*! \todo Implement this instruction +/*! \todo Check the current implementation for correctness */ int FWScript::o2_wasZoneChecked() { - warning("STUB: o2_wasZoneChecked()"); + byte param = getNextByte(); + _compare = (param < 16 && zoneData[param]); + debugC(5, kCineDebugScript, "Line: %d: o2_wasZoneChecked(%d)", _line, param); return 0; } @@ -699,13 +687,11 @@ int FWScript::o2_op9C() { int FWScript::o2_useBgScroll() { byte param = getNextByte(); - assert(param <= 8); + assert(param < 9); debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param); - if (additionalBgTable[param]) { - currentAdditionalBgIdx2 = param; - } + renderer->selectScrollBg(param); return 0; } @@ -716,12 +702,12 @@ int FWScript::o2_setAdditionalBgVScroll() { byte param2 = getNextByte(); debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2); - additionalBgVScroll = _localVars[param2]; + renderer->setScroll(_localVars[param2]); } else { uint16 param2 = getNextWord(); debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2); - additionalBgVScroll = param2; + renderer->setScroll(param2); } return 0; } diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp index e41626cad1..9b4b83f420 100644 --- a/engines/cine/texte.cpp +++ b/engines/cine/texte.cpp @@ -611,65 +611,49 @@ void freePoldatDat() { fontParamTable = 0; } -uint16 computeMessageLength(const byte *ptr, uint16 width, uint16 *numWords, uint16 *messageWidth, uint16 *lineResult) { - const byte *localPtr = ptr; - - uint16 var_2 = 0; - uint16 localLineResult = 0; - uint16 var_6 = 0; - uint16 var_8 = 0; - uint16 localMessageWidth = 0; - uint16 var_16 = 0; - uint16 finished = 0; - uint16 si = 0; - uint16 di = 0; - - while (!finished) { - byte character = *(localPtr++); - - if (character == ' ') { - var_8 = var_16; - var_6 = localMessageWidth; - localLineResult = si; - var_2 = di; - - if (si + 5 < width) { - var_16++; - si += 5; - } else { - finished = 1; - } - } else if (character == 0x7C || character == 0) { - finished = 1; - si = 0; +/*! \brief Fit a substring of text into one line of fixed width text box + * \param str Text to fit + * \param maxWidth Text box width + * \param[out] words Number of words that fit + * \param[out] width Total width of nonblank characters that fit + * \return Length of substring which fits + */ +int fitLine(const char *str, int maxWidth, int &words, int &width) { + int i, bkpWords = 0, bkpWidth = 0, bkpLen = 0; + int charWidth = 0, fullWidth = 0; + + words = 0; + width = 0; + + for (i = 0; str[i]; i++) { + if (str[i] == 0x7C) { + i++; + break; + } else if (str[i] == ' ') { + charWidth = 5; + bkpWords = words++; + bkpWidth = width; + bkpLen = i + 1; } else { - if (fontParamTable[character].characterWidth) { - uint16 var_C = fontParamTable[character].characterWidth + 1; - - if (si + var_C < width) { - si += var_C; - localMessageWidth += var_C; - } else { - finished = 1; - - if (localLineResult) { - var_16 = var_8; - localMessageWidth = var_6; - si = localLineResult; - di = var_2; - } - } - } + charWidth = fontParamTable[(unsigned char)str[i]].characterWidth + 1; + width += charWidth; } - di++; - } + if (!charWidth) { + continue; + } - *numWords = var_16; - *messageWidth = localMessageWidth; - *lineResult = si; + if (fullWidth + charWidth < maxWidth) { + fullWidth += charWidth; + } else if (fullWidth) { + words = bkpWords; + width = bkpWidth; + i = bkpLen; + break; + } + } - return di; + return i; } } // End of namespace Cine diff --git a/engines/cine/texte.h b/engines/cine/texte.h index b5eaef9211..ae82832aea 100644 --- a/engines/cine/texte.h +++ b/engines/cine/texte.h @@ -56,7 +56,7 @@ void freeErrmessDat(void); void loadPoldatDat(const char *fname); void freePoldatDat(void); -uint16 computeMessageLength(const byte *ptr, uint16 width, uint16 *numWords, uint16 *messageWidth, uint16 *lineResult); +int fitLine(const char *ptr, int maxWidth, int &words, int &width); } // End of namespace Cine diff --git a/engines/cine/unpack.cpp b/engines/cine/unpack.cpp index 4409af4b07..dcd3181242 100644 --- a/engines/cine/unpack.cpp +++ b/engines/cine/unpack.cpp @@ -30,94 +30,120 @@ namespace Cine { -struct UnpackCtx { - int size, datasize; - uint32 crc; - uint32 chk; - byte *dst; - const byte *src; -}; - -static int rcr(UnpackCtx *uc, int CF) { - int rCF = (uc->chk & 1); - uc->chk >>= 1; - if (CF) { - uc->chk |= 0x80000000; +uint32 CineUnpacker::readSource() { + if (_src < _srcBegin || _src + 4 > _srcEnd) { + _error = true; + return 0; // The source pointer is out of bounds, returning a default value } - return rCF; + uint32 value = READ_BE_UINT32(_src); + _src -= 4; + return value; } -static int nextChunk(UnpackCtx *uc) { - int CF = rcr(uc, 0); - if (uc->chk == 0) { - uc->chk = READ_BE_UINT32(uc->src); uc->src -= 4; - uc->crc ^= uc->chk; - CF = rcr(uc, 1); +uint CineUnpacker::rcr(bool inputCarry) { + uint outputCarry = (_chunk32b & 1); + _chunk32b >>= 1; + if (inputCarry) { + _chunk32b |= 0x80000000; } - return CF; + return outputCarry; } -static uint16 getCode(UnpackCtx *uc, byte numChunks) { - uint16 c = 0; - while (numChunks--) { +uint CineUnpacker::nextBit() { + uint carry = rcr(false); + // Normally if the chunk becomes zero then the carry is one as + // the end of chunk marker is always the last to be shifted out. + if (_chunk32b == 0) { + _chunk32b = readSource(); + _crc ^= _chunk32b; + carry = rcr(true); // Put the end of chunk marker in the most significant bit + } + return carry; +} + +uint CineUnpacker::getBits(uint numBits) { + uint c = 0; + while (numBits--) { c <<= 1; - if (nextChunk(uc)) { - c |= 1; - } + c |= nextBit(); } return c; } -static void unpackHelper1(UnpackCtx *uc, byte numChunks, byte addCount) { - uint16 count = getCode(uc, numChunks) + addCount + 1; - uc->datasize -= count; - while (count--) { - *uc->dst = (byte)getCode(uc, 8); - --uc->dst; +void CineUnpacker::unpackRawBytes(uint numBytes) { + if (_dst >= _dstEnd || _dst - numBytes + 1 < _dstBegin) { + _error = true; + return; // Destination pointer is out of bounds for this operation + } + while (numBytes--) { + *_dst = (byte)getBits(8); + --_dst; } } -static void unpackHelper2(UnpackCtx *uc, byte numChunks) { - uint16 i = getCode(uc, numChunks); - uint16 count = uc->size + 1; - uc->datasize -= count; - while (count--) { - *uc->dst = *(uc->dst + i); - --uc->dst; +void CineUnpacker::copyRelocatedBytes(uint offset, uint numBytes) { + if (_dst + offset >= _dstEnd || _dst - numBytes + 1 < _dstBegin) { + _error = true; + return; // Destination pointer is out of bounds for this operation + } + while (numBytes--) { + *_dst = *(_dst + offset); + --_dst; } } -bool delphineUnpack(byte *dst, const byte *src, int len) { - UnpackCtx uc; - uc.src = src + len - 4; - uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4; - uc.dst = dst + uc.datasize - 1; - uc.size = 0; - uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4; - uc.chk = READ_BE_UINT32(uc.src); uc.src -= 4; - uc.crc ^= uc.chk; - do { - if (!nextChunk(&uc)) { - uc.size = 1; - if (!nextChunk(&uc)) { - unpackHelper1(&uc, 3, 0); - } else { - unpackHelper2(&uc, 8); +bool CineUnpacker::unpack(const byte *src, uint srcLen, byte *dst, uint dstLen) { + // Initialize variables used for detecting errors during unpacking + _error = false; + _srcBegin = src; + _srcEnd = src + srcLen; + _dstBegin = dst; + _dstEnd = dst + dstLen; + + // Initialize other variables + _src = _srcBegin + srcLen - 4; + uint32 unpackedLength = readSource(); // Unpacked length in bytes + _dst = _dstBegin + unpackedLength - 1; + _crc = readSource(); + _chunk32b = readSource(); + _crc ^= _chunk32b; + + while (_dst >= _dstBegin && !_error) { + /* + Bits => Action: + 0 0 => unpackRawBytes(3 bits + 1) i.e. unpackRawBytes(1..9) + 1 1 1 => unpackRawBytes(8 bits + 9) i.e. unpackRawBytes(9..264) + 0 1 => copyRelocatedBytes(8 bits, 2) i.e. copyRelocatedBytes(0..255, 2) + 1 0 0 => copyRelocatedBytes(9 bits, 3) i.e. copyRelocatedBytes(0..511, 3) + 1 0 1 => copyRelocatedBytes(10 bits, 4) i.e. copyRelocatedBytes(0..1023, 4) + 1 1 0 => copyRelocatedBytes(12 bits, 8 bits + 1) i.e. copyRelocatedBytes(0..4095, 1..256) + */ + if (!nextBit()) { // 0... + if (!nextBit()) { // 0 0 + uint numBytes = getBits(3) + 1; + unpackRawBytes(numBytes); + } else { // 0 1 + uint numBytes = 2; + uint offset = getBits(8); + copyRelocatedBytes(offset, numBytes); } - } else { - uint16 c = getCode(&uc, 2); - if (c == 3) { - unpackHelper1(&uc, 8, 8); - } else if (c < 2) { - uc.size = c + 2; - unpackHelper2(&uc, c + 9); - } else { - uc.size = getCode(&uc, 8); - unpackHelper2(&uc, 12); + } else { // 1... + uint c = getBits(2); + if (c == 3) { // 1 1 1 + uint numBytes = getBits(8) + 9; + unpackRawBytes(numBytes); + } else if (c < 2) { // 1 0 x + uint numBytes = c + 3; + uint offset = getBits(c + 9); + copyRelocatedBytes(offset, numBytes); + } else { // 1 1 0 + uint numBytes = getBits(8) + 1; + uint offset = getBits(12); + copyRelocatedBytes(offset, numBytes); } } - } while (uc.datasize > 0 && uc.src >= src - 4); - return uc.crc == 0; + } + return !_error && (_crc == 0); } } // End of namespace Cine diff --git a/engines/cine/unpack.h b/engines/cine/unpack.h index 5f57a3531b..e16cb594a9 100644 --- a/engines/cine/unpack.h +++ b/engines/cine/unpack.h @@ -31,7 +31,86 @@ namespace Cine { -bool delphineUnpack(byte *dst, const byte *src, int len); +/** + * A LZ77 style decompressor for Delphine's data files + * used in at least Future Wars and Operation Stealth. + * @note Works backwards in the source and destination buffers. + * @note Can work with source and destination in the same buffer if there's space. + */ +class CineUnpacker { +public: + /** + * Unpacks packed data from the source buffer to the destination buffer. + * @warning Do NOT call this on data that is not packed. + * @note Source and destination buffer pointers can be the same as long as there's space for the unpacked data. + * @param src Pointer to the source buffer. + * @param srcLen Length of the source buffer. + * @param dst Pointer to the destination buffer. + * @param dstLen Length of the destination buffer. + * @return True if no errors were detected in the source data and unpacking was successful, otherwise false. + */ + bool unpack(const byte *src, uint srcLen, byte *dst, uint dstLen); +private: + /** + * Reads an unsigned big endian 32-bit integer from the source stream and goes backwards 4 bytes. + * @return If the operation is valid, an unsigned big endian 32-bit integer read from the source stream. + * @return If the operation is invalid, zero. + * @note Sets internal error state if the read operation would be out of source bounds. + */ + uint32 readSource(); + + /** + * Shifts the current internal 32-bit chunk to the right by one. + * Puts input carry into internal chunk's topmost (i.e. leftmost) bit. + * @return The least significant bit that was shifted out from the chunk. + */ + uint rcr(bool inputCarry); + + /** + * Get the next bit from the source stream. + * @note Changes the bit position in the source stream. + * @return The next bit from the source stream. + */ + uint nextBit(); + + /** + * Get bits from the source stream. + * @note Changes the bit position in the source stream. + * @param numBits Number of bits to read from the source stream. + * @return Integer value consisting of the bits read from the source stream (In range [0, (2 ** numBits) - 1]). + * @return Later the bit was read from the source, the less significant it is in the return value. + */ + uint getBits(uint numBits); + + /** + * Copy raw bytes from the input stream and write them to the destination stream. + * This is used when no adequately long match is found in the sliding window. + * @note Sets internal error state if the operation would be out of bounds. + * @param numBytes Amount of bytes to copy from the input stream + */ + void unpackRawBytes(uint numBytes); + + /** + * Copy bytes from the sliding window in the destination buffer. + * This is used when a match of two bytes or longer is found. + * @note Sets internal error state if the operation would be out of bounds. + * @param offset Offset in the sliding window + * @param numBytes Amount of bytes to copy + */ + void copyRelocatedBytes(uint offset, uint numBytes); +private: + uint32 _crc; //!< Error-detecting code (This should be zero after successful unpacking) + uint32 _chunk32b; //!< The current internal 32-bit chunk of source data + byte *_dst; //!< Pointer to the current position in the destination buffer + const byte *_src; //!< Pointer to the current position in the source buffer + + // These are used for detecting errors (e.g. out of bounds issues) during unpacking + bool _error; //!< Did an error occur during unpacking? + const byte *_srcBegin; //!< Source buffer's beginning + const byte *_srcEnd; //!< Source buffer's end + byte *_dstBegin; //!< Destination buffer's beginning + byte *_dstEnd; //!< Destination buffer's end +}; } // End of namespace Cine diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index a6bd9964c0..9b98ddb253 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -87,7 +87,6 @@ char newPrcName[20]; char newRelName[20]; char newObjectName[20]; char newMsgName[20]; -char currentBgName[8][15]; char currentCtName[15]; char currentPartName[15]; char currentDatName[30]; @@ -96,8 +95,6 @@ int16 saveVar2; byte isInPause = 0; -uint16 defaultMenuBoxColor; - byte inputVar1 = 0; uint16 inputVar2 = 0, inputVar3 = 0; @@ -114,7 +111,6 @@ CommandeType objectListCommand[20]; int16 objListTab[20]; uint16 exitEngine; -uint16 defaultMenuBoxColor2; uint16 zoneData[NUM_MAX_ZONE]; @@ -140,6 +136,7 @@ void addPlayerCommandMessage(int16 cmd) { tmp.type = 3; overlayList.push_back(tmp); + waitForPlayerClick = 1; } int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) { @@ -393,11 +390,14 @@ bool brokenSave(Common::InSaveFile &fHandle) { return broken; } +/*! \todo Implement Operation Stealth loading, this is obviously Future Wars only + */ bool CineEngine::makeLoad(char *saveName) { int16 i; int16 size; bool broken; Common::InSaveFile *fHandle; + char bgName[13]; fHandle = g_saveFileMan->openForLoading(saveName); @@ -440,7 +440,6 @@ bool CineEngine::makeLoad(char *saveName) { strcpy(newRelName, ""); strcpy(newObjectName, ""); strcpy(newMsgName, ""); - strcpy(currentBgName[0], ""); strcpy(currentCtName, ""); allowPlayerInput = 0; @@ -455,9 +454,7 @@ bool CineEngine::makeLoad(char *saveName) { fadeRequired = false; - for (i = 0; i < 16; i++) { - c_palette[i] = 0; - } + renderer->clear(); checkForPendingDataLoadSwitch = 0; @@ -473,7 +470,7 @@ bool CineEngine::makeLoad(char *saveName) { fHandle->read(currentPrcName, 13); fHandle->read(currentRelName, 13); fHandle->read(currentMsgName, 13); - fHandle->read(currentBgName[0], 13); + fHandle->read(bgName, 13); fHandle->read(currentCtName, 13); checkDataDisk(currentDisk); @@ -490,12 +487,12 @@ bool CineEngine::makeLoad(char *saveName) { loadRel(currentRelName); } - if (strlen(currentBgName[0])) { - loadBg(currentBgName[0]); + if (strlen(bgName)) { + loadBg(bgName); } if (strlen(currentCtName)) { - loadCt(currentCtName); + loadCtFW(currentCtName); } fHandle->readUint16BE(); @@ -511,13 +508,7 @@ bool CineEngine::makeLoad(char *saveName) { objectTable[i].part = fHandle->readUint16BE(); } - for (i = 0; i < 16; i++) { - c_palette[i] = fHandle->readUint16BE(); - } - - for (i = 0; i < 16; i++) { - tempPalette[i] = fHandle->readUint16BE(); - } + renderer->restorePalette(*fHandle); globalVars.load(*fHandle, NUM_MAX_VAR - 1); @@ -530,8 +521,10 @@ bool CineEngine::makeLoad(char *saveName) { } fHandle->read(commandBuffer, 0x50); + renderer->setCommand(commandBuffer); + + renderer->_cmdY = fHandle->readUint16BE(); - defaultMenuBoxColor = fHandle->readUint16BE(); bgVar0 = fHandle->readUint16BE(); allowPlayerInput = fHandle->readUint16BE(); playerCommand = fHandle->readSint16BE(); @@ -542,7 +535,8 @@ bool CineEngine::makeLoad(char *saveName) { var3 = fHandle->readUint16BE(); var2 = fHandle->readUint16BE(); commandVar2 = fHandle->readSint16BE(); - defaultMenuBoxColor2 = fHandle->readUint16BE(); + + renderer->_messageBg = fHandle->readUint16BE(); fHandle->readUint16BE(); fHandle->readUint16BE(); @@ -615,7 +609,7 @@ void makeSave(char *saveFileName) { fHandle->write(currentPrcName, 13); fHandle->write(currentRelName, 13); fHandle->write(currentMsgName, 13); - fHandle->write(currentBgName[0], 13); + renderer->saveBg(*fHandle); fHandle->write(currentCtName, 13); fHandle->writeUint16BE(0xFF); @@ -631,13 +625,7 @@ void makeSave(char *saveFileName) { fHandle->writeUint16BE(objectTable[i].part); } - for (i = 0; i < 16; i++) { - fHandle->writeUint16BE(c_palette[i]); - } - - for (i = 0; i < 16; i++) { - fHandle->writeUint16BE(tempPalette[i]); - } + renderer->savePalette(*fHandle); globalVars.save(*fHandle, NUM_MAX_VAR - 1); @@ -651,7 +639,8 @@ void makeSave(char *saveFileName) { fHandle->write(commandBuffer, 0x50); - fHandle->writeUint16BE(defaultMenuBoxColor); + fHandle->writeUint16BE(renderer->_cmdY); + fHandle->writeUint16BE(bgVar0); fHandle->writeUint16BE(allowPlayerInput); fHandle->writeUint16BE(playerCommand); @@ -662,7 +651,8 @@ void makeSave(char *saveFileName) { fHandle->writeUint16BE(var3); fHandle->writeUint16BE(var2); fHandle->writeUint16BE(commandVar2); - fHandle->writeUint16BE(defaultMenuBoxColor2); + + fHandle->writeUint16BE(renderer->_messageBg); fHandle->writeUint16BE(0xFF); fHandle->writeUint16BE(0x1E); @@ -864,26 +854,6 @@ void CineEngine::makeSystemMenu(void) { } } -int drawChar(byte character, int16 x, int16 y) { - if (character == ' ') { - x += 5; - } else { - byte characterWidth = fontParamTable[character].characterWidth; - - if (characterWidth) { - byte characterIdx = fontParamTable[character].characterIdx; - if (g_cine->getGameType() == Cine::GType_OS) { - drawSpriteRaw2(textTable[characterIdx][0], 0, 2, 8, page1Raw, x, y); - } else { - drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y); - } - x += characterWidth + 1; - } - } - - return x; -} - void drawMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 offset, int16 color, byte* page) { gfxDrawLine(x + offset, y + offset, x + width - offset, y + offset, color, page); // top gfxDrawLine(x + offset, currentY + 4 - offset, x + width - offset, currentY + 4 - offset, color, page); // bottom @@ -896,49 +866,6 @@ void drawDoubleMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 c drawMessageBox(x, y, width, currentY, 0, color, page); } -void makeTextEntry(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width) { - byte color = 2; - byte color2 = defaultMenuBoxColor2; - int16 paramY = (height * 9) + 10; - int16 currentX, currentY; - int16 i; - uint16 j; - byte currentChar; - - if (X + width > 319) { - X = 319 - width; - } - - if (Y + paramY > 199) { - Y = 199 - paramY; - } - - hideMouse(); - blitRawScreen(page1Raw); - - gfxDrawPlainBoxRaw(X, Y, X + width, Y + 4, color2, page1Raw); - - currentX = X + 4; - currentY = Y + 4; - - for (i = 0; i < height; i++) { - gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 9, color2, page1Raw); - currentX = X + 4; - - for (j = 0; j < strlen(commandList[i]); j++) { - currentChar = commandList[i][j]; - currentX = drawChar(currentChar, currentX, currentY); - } - - currentY += 9; - } - - gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 4, color2, page1Raw); // bottom part - drawDoubleMessageBox(X, Y, width, currentY, color, page1Raw); - - blitRawScreen(page1Raw); -} - void processInventory(int16 x, int16 y) { int16 listSize = buildObjectListCommand(-2); uint16 button; @@ -946,7 +873,8 @@ void processInventory(int16 x, int16 y) { if (!listSize) return; - makeTextEntry(objectListCommand, listSize, x, y, 140); + renderer->drawMenu(objectListCommand, listSize, x, y, 140, -1); + renderer->blit(); do { manageEvents(); @@ -1085,7 +1013,7 @@ void makeCommandLine(void) { } if (!disableSystemMenu) { - isDrawCommandEnabled = 1; + renderer->setCommand(commandBuffer); } } @@ -1094,13 +1022,8 @@ uint16 needMouseSave = 0; uint16 menuVar4 = 0; uint16 menuVar5 = 0; -int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, - uint16 width, bool recheckValue) { - byte color = 2; - byte color2 = defaultMenuBoxColor2; +int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width, bool recheckValue) { int16 paramY; - int16 currentX, currentY; - int16 i; uint16 button; int16 var_A; int16 di; @@ -1110,7 +1033,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, int16 var_14; int16 currentSelection, oldSelection; int16 var_4; - byte currentChar; if (disableSystemMenu) return -1; @@ -1125,30 +1047,8 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, Y = 199 - paramY; } - hideMouse(); - blitRawScreen(page1Raw); - - gfxDrawPlainBoxRaw(X, Y, X + width, Y + 4, color2, page1Raw); - - currentX = X + 4; - currentY = Y + 4; - - for (i = 0; i < height; i++) { - gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 9, color2, page1Raw); - currentX = X + 4; - - for (j = 0; j < strlen(commandList[i]); j++) { - currentChar = commandList[i][j]; - currentX = drawChar(currentChar, currentX, currentY); - } - - currentY += 9; - } - - gfxDrawPlainBoxRaw(X, currentY, X + width, currentY + 4, color2, page1Raw); // bottom part - drawDoubleMessageBox(X, Y, width, currentY, color, page1Raw); - - blitRawScreen(page1Raw); + renderer->drawMenu(commandList, height, X, Y, width, -1); + renderer->blit(); do { manageEvents(); @@ -1160,15 +1060,9 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, currentSelection = 0; di = currentSelection * 9 + Y + 4; - gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, 0, page1Raw); // draw black box behind selection - currentX = X + 4; - - for (j = 0; j < strlen(commandList[currentSelection]); j++) { - currentChar = commandList[currentSelection][j]; - currentX = drawChar(currentChar, currentX, di); - } - blitRawScreen(page1Raw); + renderer->drawMenu(commandList, height, X, Y, width, currentSelection); + renderer->blit(); manageEvents(); getMouseData(mouseUpdateStatus, &button, (uint16 *)&mouseX, (uint16 *)&mouseY); @@ -1219,29 +1113,10 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, hideMouse(); } - di = oldSelection * 9 + Y + 4; - - gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, color2, page1Raw); // restore color - - currentX = X + 4; - - for (j = 0; j < strlen(commandList[oldSelection]); j++) { - currentChar = commandList[oldSelection][j]; - currentX = drawChar(currentChar, currentX, di); - } - di = currentSelection * 9 + Y + 4; - gfxDrawPlainBoxRaw(X + 2, di - 1, X + width - 2, di + 7, 0, page1Raw); // black new - - currentX = X + 4; - - for (j = 0; j < strlen(commandList[currentSelection]); j++) { - currentChar = commandList[currentSelection][j]; - currentX = drawChar(currentChar, currentX, di); - } - - blitRawScreen(page1Raw); + renderer->drawMenu(commandList, height, X, Y, width, currentSelection); + renderer->blit(); // if (needMouseSave) { // gfxRedrawMouseCursor(); @@ -1271,38 +1146,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, return currentSelection; } -void drawMenuBox(char *command, int16 x, int16 y) { - byte j; - byte lColor = 2; - - hideMouse(); - - gfxDrawPlainBoxRaw(x, y, x + 300, y + 10, 0, page2Raw); - - drawMessageBox(x, y, 300, y + 6, -1, lColor, page2Raw); - - x += 2; - y += 2; - - for (j = 0; j < strlen(command); j++) { - byte currentChar = command[j]; - - if (currentChar == ' ') { - x += 5; - } else { - byte characterWidth = fontParamTable[currentChar].characterWidth; - - if (characterWidth) { - byte characterIdx = fontParamTable[currentChar].characterIdx; - drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page2Raw, x, y); - x += characterWidth + 1; - } - } - } - -// gfxRedrawMouseCursor(); -} - void makeActionMenu(void) { uint16 mouseButton; uint16 mouseX; @@ -1342,11 +1185,6 @@ uint16 executePlayerInput(void) { } if (allowPlayerInput) { - if (isDrawCommandEnabled) { - drawMenuBox(commandBuffer, 10, defaultMenuBoxColor); - isDrawCommandEnabled = 0; - } - getMouseData(mouseUpdateStatus, &mouseButton, &mouseX, &mouseY); while (mouseButton && currentEntry < 200) { @@ -1393,7 +1231,6 @@ uint16 executePlayerInput(void) { if (choiceResultTable[playerCommand] == commandVar1) { int16 relEntry; - drawMenuBox(commandBuffer, 10, defaultMenuBoxColor); SelectedObjStruct obj; obj.idx = commandVar3[0]; obj.param = commandVar3[1]; @@ -1410,41 +1247,40 @@ uint16 executePlayerInput(void) { commandVar1 = 0; strcpy(commandBuffer, ""); + renderer->setCommand(""); } } else { globalVars[VAR_MOUSE_X_POS] = mouseX; globalVars[VAR_MOUSE_Y_POS] = mouseY; } } - } else { - if (mouseButton & 2) { - if (mouseButton & 1) { - g_cine->makeSystemMenu(); - } + } else if (mouseButton & 2) { + if (mouseButton & 1) { + g_cine->makeSystemMenu(); + } - makeActionMenu(); - makeCommandLine(); - } else { - int16 objIdx; + makeActionMenu(); + makeCommandLine(); + } else { + int16 objIdx; - objIdx = getObjectUnderCursor(mouseX, mouseY); + objIdx = getObjectUnderCursor(mouseX, mouseY); - if (commandVar2 != objIdx) { - if (objIdx != -1) { - char command[256]; + if (commandVar2 != objIdx) { + if (objIdx != -1) { + char command[256]; - strcpy(command, commandBuffer); - strcat(command, " "); - strcat(command, objectTable[objIdx].name); + strcpy(command, commandBuffer); + strcat(command, " "); + strcat(command, objectTable[objIdx].name); - drawMenuBox(command, 10, defaultMenuBoxColor); - } else { - isDrawCommandEnabled = 1; - } + renderer->setCommand(command); + } else { + isDrawCommandEnabled = 1; } - - commandVar2 = objIdx; } + + commandVar2 = objIdx; } } else { if (mouseButton & 2) { @@ -1653,257 +1489,9 @@ void drawSprite(Common::List<overlay>::iterator it, const byte *spritePtr, const free(msk); } -int16 additionalBgVScroll = 0; - -void backupOverlayPage(void) { - byte *scrollBg; - byte *bgPage = additionalBgTable[currentAdditionalBgIdx]; - - if (bgPage) { - if (!additionalBgVScroll) { - memcpy(page1Raw, bgPage, 320 * 200); - } else { - scrollBg = additionalBgTable[currentAdditionalBgIdx2]; - - for (int16 i = additionalBgVScroll; i < 200 + additionalBgVScroll; i++) { - if (i > 200) { - memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320); - } else { - memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320); - } - } - } - } -} - -void drawMessage(const char *messagePtr, int16 x, int16 y, int16 width, int16 color) { - byte color2 = 2; - byte endOfMessageReached = 0; - int16 localX, localY, localWidth; - uint16 messageLength = 0, numWords = 0, messageWidth = 0; - uint16 lineResult, fullLineWidth; - uint16 interWordSize, interWordSizeRemain; - const char *endOfMessagePtr; - byte currentChar; //, characterWidth; - - gfxDrawPlainBoxRaw(x, y, x + width, y + 4, color, page1Raw); - - localX = x + 4; - localY = y + 4; - localWidth = width - 8; - - do { - messageLength = 0; - - while (messagePtr[messageLength] == ' ') { - messageLength++; - } - - messagePtr += messageLength; - - messageLength = computeMessageLength((const byte *)messagePtr, localWidth, &numWords, &messageWidth, &lineResult); - - endOfMessagePtr = messagePtr + messageLength; - - if (lineResult) { - fullLineWidth = localWidth - messageWidth; - - if (numWords) { - interWordSize = fullLineWidth / numWords; - interWordSizeRemain = fullLineWidth % numWords; - } else { - interWordSize = 5; - interWordSizeRemain = 0; - } - } else { - interWordSize = 5; - interWordSizeRemain = 0; - } - - gfxDrawPlainBoxRaw(x, localY, x + width, localY + 9, color, page1Raw); - - do { - currentChar = *(messagePtr++); - - if (currentChar == 0) { - endOfMessageReached = 1; - } else if (currentChar == ' ') { - localX += interWordSizeRemain + interWordSize; - - if (interWordSizeRemain) - interWordSizeRemain = 0; - } else { - localX = drawChar(currentChar, localX, localY); - } - } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached); - - localX = x + 4; - localY += 9; - } while (!endOfMessageReached); - - gfxDrawPlainBoxRaw(x, localY, x + width, localY + 4, color, page1Raw); - - drawDoubleMessageBox(x, y, width, localY, color2, page1Raw); -} - -void drawDialogueMessage(byte msgIdx, int16 x, int16 y, int16 width, int16 color) { - if (msgIdx >= messageTable.size()) { -// removeOverlay(msgIdx, 2); - return; - } - - _messageLen += messageTable[msgIdx].size(); - drawMessage(messageTable[msgIdx].c_str(), x, y, width, color); - - // this invalidates the iterator in drawOverlays() -// removeOverlay(msgIdx, 2); -} - -void drawFailureMessage(byte cmd) { - byte msgIdx = cmd * 4 + g_cine->_rnd.getRandomNumber(3); - - const char *messagePtr = failureMessages[msgIdx]; - int len = strlen(messagePtr); - - _messageLen += len; - - int16 width = 6 * len + 20; - - if (width > 300) - width = 300; - - int16 x = (320 - width) / 2; - int16 y = 80; - int16 color = 4; - - drawMessage(messagePtr, x, y, width, color); - - // this invalidates the iterator in drawOverlays() -// removeOverlay(cmd, 3); -} - -void drawOverlays(void) { - uint16 width, height; - AnimData *pPart; - int16 x, y; - objectStruct *objPtr; - byte messageIdx; +void removeMessages() { Common::List<overlay>::iterator it; - backupOverlayPage(); - - _messageLen = 0; - - for (it = overlayList.begin(); it != overlayList.end(); ++it) { - switch (it->type) { - case 0: // sprite - assert(it->objIdx < NUM_MAX_OBJECT); - - objPtr = &objectTable[it->objIdx]; - x = objPtr->x; - y = objPtr->y; - - if (objPtr->frame < 0) { - continue; - } - - pPart = &animDataTable[objPtr->frame]; - width = pPart->_realWidth; - height = pPart->_height; - - if (!pPart->data()) { - continue; - } - - // drawSprite ignores masks of Operation Stealth sprites - drawSprite(it, pPart->data(), pPart->mask(), width, height, page1Raw, x, y); - break; - - case 2: // text - // gfxWaitVSync(); - // hideMouse(); - - messageIdx = it->objIdx; - x = it->x; - y = it->y; - width = it->width; - height = it->color; - - blitRawScreen(page1Raw); - - drawDialogueMessage(messageIdx, x, y, width, height); - - // blitScreen(page0, NULL); - // gfxRedrawMouseCursor(); - - waitForPlayerClick = 1; - - break; - - case 3: - // gfxWaitSync() - // hideMouse(); - - blitRawScreen(page1Raw); - - drawFailureMessage(it->objIdx); - - // blitScreen(page0, NULL); - // gfxRedrawMouseCursor(); - - waitForPlayerClick = 1; - - break; - - case 4: - assert(it->objIdx < NUM_MAX_OBJECT); - - objPtr = &objectTable[it->objIdx]; - x = objPtr->x; - y = objPtr->y; - - if (objPtr->frame < 0) { - continue; - } - - assert(objPtr->frame < NUM_MAX_ANIMDATA); - - pPart = &animDataTable[objPtr->frame]; - - width = pPart->_realWidth; - height = pPart->_height; - - if (!pPart->data()) { - continue; - } - - gfxFillSprite(pPart->data(), width, height, page1Raw, x, y); - break; - - case 20: - assert(it->objIdx < NUM_MAX_OBJECT); - - objPtr = &objectTable[it->objIdx]; - x = objPtr->x; - y = objPtr->y; - var5 = it->x; - - if (objPtr->frame < 0 || var5 > 8 || !additionalBgTable[var5] || animDataTable[objPtr->frame]._bpp != 1) { - continue; - } - - width = animDataTable[objPtr->frame]._realWidth; - height = animDataTable[objPtr->frame]._height; - - if (!animDataTable[objPtr->frame].data()) { - continue; - } - - maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), width, height, page1Raw, x, y); - break; - } - } - for (it = overlayList.begin(); it != overlayList.end(); ) { if (it->type == 2 || it->type == 3) { it = overlayList.erase(it); @@ -1978,115 +1566,96 @@ void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 par tmp.color = param5; overlayList.push_back(tmp); + waitForPlayerClick = 1; } -SeqListElement seqList; +Common::List<SeqListElement> seqList; void removeSeq(uint16 param1, uint16 param2, uint16 param3) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; + Common::List<SeqListElement>::iterator it; - while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { - tempHead = currentHead; - currentHead = tempHead->next; - } - - if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { - currentHead->var4 = -1; + for (it = seqList.begin(); it != seqList.end(); ++it) { + if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) { + it->var4 = -1; + break; + } } } uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; - - while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { - tempHead = currentHead; - currentHead = tempHead->next; - } + Common::List<SeqListElement>::iterator it; - if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { - return 1; + for (it = seqList.begin(); it != seqList.end(); ++it) { + if (it->objIdx == param1 && it->var4 == param2 && it->varE == param3) { + return 1; + } } return 0; } -void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; - SeqListElement *newElement; - - currentHead = tempHead->next; - - while (currentHead && currentHead->varE < param7) { - tempHead = currentHead; - currentHead = tempHead->next; - } - - newElement = new SeqListElement; - - newElement->next = tempHead->next; - tempHead->next = newElement; - - newElement->var6 = param0; - newElement->var4 = param1; - newElement->var8 = param2; - newElement->varA = param3; - newElement->varC = param4; - newElement->var14 = 0; - newElement->var16 = 0; - newElement->var18 = param5; - newElement->var1A = param6; - newElement->varE = param7; - newElement->var10 = param8; - newElement->var12 = param8; - newElement->var1C = 0; - newElement->var1E = 0; -} - -void resetSeqList() { - seqList.next = NULL; +void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) { + Common::List<SeqListElement>::iterator it; + SeqListElement tmp; + + for (it = seqList.begin(); it != seqList.end() && it->varE < param7; ++it) ; + + tmp.objIdx = objIdx; + tmp.var4 = param1; + tmp.var8 = param2; + tmp.frame = frame; + tmp.varC = param4; + tmp.var14 = 0; + tmp.var16 = 0; + tmp.var18 = param5; + tmp.var1A = param6; + tmp.varE = param7; + tmp.var10 = param8; + tmp.var12 = param8; + tmp.var1C = 0; + tmp.var1E = 0; + + seqList.insert(it, tmp); } -void computeMove1(SeqListElement *element, int16 x, int16 y, int16 param1, +void computeMove1(SeqListElement &element, int16 x, int16 y, int16 param1, int16 param2, int16 x2, int16 y2) { - element->var16 = 0; - element->var14 = 0; + element.var16 = 0; + element.var14 = 0; if (y2) { if (y - param2 > y2) { - element->var16 = 2; + element.var16 = 2; } if (y + param2 < y2) { - element->var16 = 1; + element.var16 = 1; } } if (x2) { if (x - param1 > x2) { - element->var14 = 2; + element.var14 = 2; } if (x + param1 < x2) { - element->var14 = 1; + element.var14 = 1; } } } -uint16 computeMove2(SeqListElement *element) { +uint16 computeMove2(SeqListElement &element) { int16 returnVar = 0; - if (element->var16 == 1) { + if (element.var16 == 1) { returnVar = 4; - } else if (element->var16 == 2) { + } else if (element.var16 == 2) { returnVar = 3; } - if (element->var14 == 1) { + if (element.var14 == 1) { returnVar = 1; - } else if (element->var14 == 2) { + } else if (element.var14 == 2) { returnVar = 2; } @@ -2165,14 +1734,13 @@ void resetGfxEntityEntry(uint16 objIdx) { #endif } -uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) { +uint16 addAni(uint16 param1, uint16 objIdx, const byte *ptr, SeqListElement &element, uint16 param3, int16 *param4) { const byte *currentPtr = ptr; const byte *ptrData; const byte *ptr2; int16 di; assert(ptr); - assert(element); assert(param4); dummyU16 = READ_BE_UINT16((currentPtr + param1 * 2) + 8); @@ -2181,25 +1749,25 @@ uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *ele assert(*ptrData); - di = (objectTable[param2].costume + 1) % (*ptrData); + di = (objectTable[objIdx].costume + 1) % (*ptrData); ptr2 = (ptrData + (di * 8)) + 1; - if ((checkCollision(param2, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) { + if ((checkCollision(objIdx, ptr2[0], ptr2[1], ptr2[2], ptr[0]) & 1)) { return 0; } - objectTable[param2].x += (int8)ptr2[4]; - objectTable[param2].y += (int8)ptr2[5]; - objectTable[param2].mask += (int8)ptr2[6]; + objectTable[objIdx].x += (int8)ptr2[4]; + objectTable[objIdx].y += (int8)ptr2[5]; + objectTable[objIdx].mask += (int8)ptr2[6]; - if (objectTable[param2].frame) { - resetGfxEntityEntry(param2); + if (objectTable[objIdx].frame) { + resetGfxEntityEntry(objIdx); } - objectTable[param2].frame = ptr2[7] + element->var8; + objectTable[objIdx].frame = ptr2[7] + element.var8; - if (param3 || !element->var14) { - objectTable[param2].costume = di; + if (param3 || !element.var14) { + objectTable[objIdx].costume = di; } else { *param4 = di; } @@ -2207,86 +1775,86 @@ uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *ele return 1; } -void processSeqListElement(SeqListElement *element) { - int16 x = objectTable[element->var6].x; - int16 y = objectTable[element->var6].y; - const byte *ptr1 = animDataTable[element->varA].data(); +void processSeqListElement(SeqListElement &element) { + int16 x = objectTable[element.objIdx].x; + int16 y = objectTable[element.objIdx].y; + const byte *ptr1 = animDataTable[element.frame].data(); int16 var_10; int16 var_4; int16 var_2; - if (element->var12 < element->var10) { - element->var12++; + if (element.var12 < element.var10) { + element.var12++; return; } - element->var12 = 0; + element.var12 = 0; if (ptr1) { uint16 param1 = ptr1[1]; uint16 param2 = ptr1[2]; - if (element->varC != 255) { + if (element.varC != 255) { // FIXME: Why is this here? Fingolfin gets lots of these // in his copy of Operation Stealth (value 0 or 236) under // Mac OS X. Maybe it's a endian issue? At least the graphics // in the copy protection screen are partially messed up. - warning("processSeqListElement: varC = %d", element->varC); + warning("processSeqListElement: varC = %d", element.varC); } if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) { computeMove1(element, ptr1[4] + x, ptr1[5] + y, param1, param2, globalVars[VAR_MOUSE_X_POS], globalVars[VAR_MOUSE_Y_POS]); } else { - element->var16 = 0; - element->var14 = 0; + element.var16 = 0; + element.var14 = 0; } var_10 = computeMove2(element); if (var_10) { - element->var1C = var_10; - element->var1E = var_10; + element.var1C = var_10; + element.var1E = var_10; } var_4 = -1; - if ((element->var16 == 1 - && !addAni(3, element->var6, ptr1, element, 0, &var_4)) || (element->var16 == 2 && !addAni(2, element->var6, ptr1, element, 0, + if ((element.var16 == 1 + && !addAni(3, element.objIdx, ptr1, element, 0, &var_4)) || (element.var16 == 2 && !addAni(2, element.objIdx, ptr1, element, 0, &var_4))) { - if (element->varC == 255) { + if (element.varC == 255) { globalVars[VAR_MOUSE_Y_POS] = 0; } } - if ((element->var14 == 1 - && !addAni(0, element->var6, ptr1, element, 1, &var_2))) { - if (element->varC == 255) { + if ((element.var14 == 1 + && !addAni(0, element.objIdx, ptr1, element, 1, &var_2))) { + if (element.varC == 255) { globalVars[VAR_MOUSE_X_POS] = 0; if (var_4 != -1) { - objectTable[element->var6].costume = var_4; + objectTable[element.objIdx].costume = var_4; } } } - if ((element->var14 == 2 && !addAni(1, element->var6, ptr1, element, 1, &var_2))) { - if (element->varC == 255) { + if ((element.var14 == 2 && !addAni(1, element.objIdx, ptr1, element, 1, &var_2))) { + if (element.varC == 255) { globalVars[VAR_MOUSE_X_POS] = 0; if (var_4 != -1) { - objectTable[element->var6].costume = var_4; + objectTable[element.objIdx].costume = var_4; } } } - if (element->var16 + element->var14) { - if (element->var1C) { - if (element->var1E) { - objectTable[element->var6].costume = 0; - element->var1E = 0; + if (element.var16 + element.var14) { + if (element.var1C) { + if (element.var1E) { + objectTable[element.objIdx].costume = 0; + element.var1E = 0; } - addAni(element->var1C + 3, element->var6, ptr1, element, 1, (int16 *) & var2); + addAni(element.var1C + 3, element.objIdx, ptr1, element, 1, (int16 *) & var2); } } @@ -2295,119 +1863,28 @@ void processSeqListElement(SeqListElement *element) { } void processSeqList(void) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; + Common::List<SeqListElement>::iterator it; - currentHead = tempHead->next; - - while (currentHead) { - if (currentHead->var4 != -1) { - processSeqListElement(currentHead); + for (it = seqList.begin(); it != seqList.end(); ++it) { + if (it->var4 == -1) { + continue; } - tempHead = currentHead; - currentHead = tempHead->next; + processSeqListElement(*it); } } bool makeTextEntryMenu(const char *messagePtr, char *inputString, int stringMaxLength, int y) { - int16 color = 2; - byte color2 = defaultMenuBoxColor2; - byte endOfMessageReached = 0; - int16 localX, localY, localWidth; - int margins = 16; int len = strlen(messagePtr); int16 width = 6 * len + 20; - uint16 messageLength = 0, numWords = 0, messageWidth = 0; - uint16 lineResult, fullLineWidth; - uint16 interWordSize, interWordSizeRemain; - const char *endOfMessagePtr; - byte currentChar, characterWidth; width = CLIP((int)width, 180, 250); int16 x = (320 - width) / 2; - gfxDrawPlainBoxRaw(x - margins, y, x + width + margins, y + 4, color2, page1Raw); - - localX = x + 4; - localY = y + 4; - localWidth = width; - getKeyData(); // clear input key - do { - messageLength = 0; - - while (messagePtr[messageLength] == ' ') { - messageLength++; - } - - messagePtr += messageLength; - - messageLength = computeMessageLength((const byte *)messagePtr, localWidth, &numWords, &messageWidth, &lineResult); - - endOfMessagePtr = messagePtr + messageLength; - - if (lineResult) { - fullLineWidth = localWidth - messageWidth; - - if (numWords) { - interWordSize = fullLineWidth / numWords; - interWordSizeRemain = fullLineWidth % numWords; - } else { - interWordSize = 5; - interWordSizeRemain = 0; - } - } else { - interWordSize = 5; - interWordSizeRemain = 0; - } - - gfxDrawPlainBoxRaw(x - margins, localY, x + width + margins, localY + 9, color2, page1Raw); - - do { - currentChar = *(messagePtr++); - - if (currentChar == 0) { - endOfMessageReached = 1; - } else if (currentChar == ' ') { - localX += interWordSizeRemain + interWordSize; - - if (interWordSizeRemain) - interWordSizeRemain = 0; - } else { - characterWidth = fontParamTable[currentChar].characterWidth; - - if (characterWidth) { - byte characterIdx = fontParamTable[currentChar].characterIdx; - drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, localX, localY); - localX += characterWidth + 1; - } - } - } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached); - - localX = x + 4; - localY += 9; - } while (!endOfMessageReached); - - // Input string - gfxDrawPlainBoxRaw(x - margins, localY, x + width + margins, localY + 9, color2, page1Raw); - localY += 9; - - x -= margins; - width += margins * 2; - - gfxDrawPlainBoxRaw(x, localY, x + width, localY + 4, color2, page1Raw); - - drawDoubleMessageBox(x, y, width, localY, color, page1Raw); - - x += margins; - width -= margins * 2; - localY -= 9; - - int quit = 0; bool redraw = true; CommandeType tempString; @@ -2416,24 +1893,8 @@ bool makeTextEntryMenu(const char *messagePtr, char *inputString, int stringMaxL while (!quit) { if (redraw) { - gfxDrawPlainBoxRaw(x, localY - 1, x + width, localY + 8, 0, page1Raw); - - int currentX = x + 4; - - for (uint j = 0; j < strlen(inputString); j++) { - currentChar = inputString[j]; - currentX = drawChar(currentChar, currentX, localY); - - // draw cursor here - if (inputPos == (int)(j + 2)) - gfxDrawLine(currentX, localY - 1, currentX, localY + 8, color, page1Raw); - - } - - if (strlen(inputString) == 0 || inputPos == 1) // cursor wasn't yet drawn - gfxDrawLine(x + 4, localY - 1, x + 4, localY + 8, color, page1Raw); - - blitRawScreen(page1Raw); + renderer->drawInputBox(messagePtr, inputString, inputPos, x - 16, y, width + 32); + renderer->blit(); redraw = false; } diff --git a/engines/cine/various.h b/engines/cine/various.h index f906b2aa19..91662c16ff 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -43,11 +43,10 @@ extern bool disableSystemMenu; extern bool inMenu; struct SeqListElement { - struct SeqListElement *next; int16 var4; - int16 var6; + uint16 objIdx; int16 var8; - int16 varA; + int16 frame; int16 varC; int16 varE; int16 var10; @@ -60,7 +59,7 @@ struct SeqListElement { int16 var1E; }; -extern SeqListElement seqList; +extern Common::List<SeqListElement> seqList; extern uint16 var2; extern uint16 var3; @@ -97,7 +96,6 @@ extern char newRelName[20]; extern char newObjectName[20]; extern char newMsgName[20]; -extern char currentBgName[8][15]; extern char currentCtName[15]; extern char currentPartName[15]; @@ -130,20 +128,16 @@ struct SelectedObjStruct { int16 param; }; -extern uint16 defaultMenuBoxColor; -extern uint16 defaultMenuBoxColor2; - #define NUM_MAX_ZONE 16 extern uint16 zoneData[NUM_MAX_ZONE]; void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5); -extern int16 additionalBgVScroll; +void removeMessages(); void removeSeq(uint16 param1, uint16 param2, uint16 param3); uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3); -void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8); -void resetSeqList(); +void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8); void processSeqList(void); bool makeTextEntryMenu(const char *caption, char *string, int strLen, int y); diff --git a/engines/cine/xref.txt b/engines/cine/xref.txt index 3640ef83d6..5a8d2eef0f 100644 --- a/engines/cine/xref.txt +++ b/engines/cine/xref.txt @@ -1,4 +1,4 @@ -script.cpp: +script_fw.cpp: setupOpcodes() - replaced with FWScript/OSScript class members getNextByte() - replaced with RawScript/FWScript class members getNextWord() - replaced with RawScript/FWScript class members @@ -89,6 +89,9 @@ o1_disableSystemMenu() - replaced with FWScript::o1_disableSystemMenu() o1_loadMask5() - replaced with FWScript::o1_loadMask5() o1_unloadMask5() - replaced with FWScript::o1_unloadMask5() +palRotate() - modified and moved to pal.cpp + +script_os.cpp: o2_loadPart() - replaced with FWScript::o2_loadPart() o2_addSeqListElement() - replaced with FWScript::o2_addSeqListElement() o2_removeSeq() - replaced with FWScript::o2_removeSeq() @@ -134,20 +137,48 @@ releaseObjectScripts() - removed (obsoleted by Common::List::clear()) various.cpp: setupScriptList() - removed (obsoleted by new makeLoad() and loadScriptFromSave() implementation) +drawChar() - removed (obsoleted by FWRenderer::drawChar()) +makeTextEntry() - removed (obsoleted by FWRenderer::drawMenu()) +drawMenuBox() - removed (obsoleted by FWRenderer::drawCommand()) +backupOverlayPage() - removed (obsoleted by FWRenderer::drawBackground()) +drawMessage() - removed (obsoleted by FWRenderer::drawMessage()) +drawDialogueMessage() - removed (obsoleted by FWRenderer::renderOverlay()) +drawFailureMessage() - removed (obsoleted by FWRenderer::renderOverlay()) +drawOverlays() - removed (obsoleted by FWRenderer::drawOverlays()) +resetSeqList() - removed (obsoleted by Common::List) anim.cpp: freeAnimData() - replaced with animData::clear() allocFrame() - replaced with animData::load() reserveFrame() - replaced with animData::load() -bg_list.cpp +bg_list.cpp: reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and loadBgIncrustFromSave() implementation) freeBgIncrustList() - removed (obsoleted by Common::List::clear()) -object.cpp +object.cpp: unloadAllMasks() - removed (obsoleted by Common::List::clear()) resetMessageHead() - removed (obsoleted by Common::List) freeOverlay() - removed (duplicate of removeOverlay) removeOverlayElement() - renamed to removeOverlay loadOverlayElement() - renamed to addOverlay + +gfx.cpp: +gfxInit() - removed (obsoleted by FWRenderer) +gfxDestroy() - removed (obsoleted by FWRenderer) +transformColor() - moved to pal.cpp +transformPaletteRange() - modified and moved to pal.cpp +gfxCopyRawPage() - removed (obsoleted by FWRenderer) +gfxFlipRawPage() - removed (obsoleted by FWRenderer::blit() and + FWRenderer::refreshPalette()) +fadeToBlack() - removed (obsoleted by FWRenderer::fadeToBlack()) +blitRawScreen() - removed (obsoleted by FWRenderer) +flip() - removed (obsoleted by FWRenderer::reloadPalette()) + +bg.cpp: +loadCt() - split into loadCtFW() and loadCtOS() +loadBgHigh() - removed (obsoleted by OSRenderer::loadBg256()) + +texte.cpp: +computeMessageLength() - replaced with fitLine() diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h index c7d597dbd6..60afe5fa4c 100644 --- a/engines/cruise/cruise_main.h +++ b/engines/cruise/cruise_main.h @@ -45,7 +45,6 @@ #include "cruise/stack.h" #include "cruise/script.h" #include "cruise/various.h" -#include "cruise/stringSupport.h" #include "cruise/function.h" #include "cruise/saveload.h" #include "cruise/linker.h" diff --git a/engines/cruise/module.mk b/engines/cruise/module.mk index 384d7a1ecb..8db5b1da44 100644 --- a/engines/cruise/module.mk +++ b/engines/cruise/module.mk @@ -27,7 +27,6 @@ MODULE_OBJS := \ saveload.o \ script.o \ stack.o \ - stringSupport.o \ various.o \ vars.o \ volume.o diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp new file mode 100644 index 0000000000..10ce415c2c --- /dev/null +++ b/engines/drascula/actors.cpp @@ -0,0 +1,462 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::placeIgor() { + int pos_igor[6] = { 1, 0, igorX, igorY, 54, 61 }; + + if (currentChapter == 4) { + pos_igor[1] = 138; + } else { + if (trackIgor == 3) + pos_igor[1] = 138; + else if (trackIgor == 1) + pos_igor[1] = 76; + } + + copyRectClip(pos_igor, frontSurface, screenSurface); +} + +void DrasculaEngine::placeDrascula() { + int pos_dr[6] = { 0, 122, drasculaX, drasculaY, 45, 77 }; + + if (trackDrascula == 1) + pos_dr[0] = 47; + else if (trackDrascula == 0) + pos_dr[0] = 1; + else if (trackDrascula == 3 && currentChapter == 1) + pos_dr[0] = 93; + + if (currentChapter == 6) + copyRectClip(pos_dr, drawSurface2, screenSurface); + else + copyRectClip(pos_dr, backSurface, screenSurface); +} + +void DrasculaEngine::placeBJ() { + int pos_bj[6] = { 0, 99, bjX, bjY, 26, 76 }; + + if (trackBJ == 3) + pos_bj[0] = 10; + else if (trackBJ == 0) + pos_bj[0] = 37; + + copyRectClip(pos_bj, drawSurface3, screenSurface); +} + +void DrasculaEngine::hiccup(int counter) { + int y = 0, trackCharacter = 0; + if (currentChapter == 3) + y = -1; + + do { + counter--; + + updateRoom(); + if (currentChapter == 3) + updateScreen(0, 0, 0, y, 320, 200, screenSurface); + else + updateScreen(0, 1, 0, y, 320, 198, screenSurface); + + if (trackCharacter == 0) + y++; + else + y--; + + if (currentChapter == 3) { + if (y == 1) + trackCharacter = 1; + if (y == -1) + trackCharacter = 0; + } else { + if (y == 2) + trackCharacter = 1; + if (y == 0) + trackCharacter = 0; + } + } while (counter > 0); + + updateRoom(); + updateScreen(); +} + +void DrasculaEngine::startWalking() { + characterMoved = 1; + + stepX = STEP_X; + stepY = STEP_Y; + + if (currentChapter == 2) { + if ((roomX < curX) && (roomY <= (curY + curHeight))) + quadrant_1(); + else if ((roomX < curX) && (roomY > (curY + curHeight))) + quadrant_3(); + else if ((roomX > curX + curWidth) && (roomY <= (curY + curHeight))) + quadrant_2(); + else if ((roomX > curX + curWidth) && (roomY > (curY + curHeight))) + quadrant_4(); + else if (roomY < curY + curHeight) + walkUp(); + else if (roomY > curY + curHeight) + walkDown(); + } else { + if ((roomX < curX + curWidth / 2 ) && (roomY <= (curY + curHeight))) + quadrant_1(); + else if ((roomX < curX + curWidth / 2) && (roomY > (curY + curHeight))) + quadrant_3(); + else if ((roomX > curX + curWidth / 2) && (roomY <= (curY + curHeight))) + quadrant_2(); + else if ((roomX > curX + curWidth / 2) && (roomY > (curY + curHeight))) + quadrant_4(); + else + characterMoved = 0; + } + startTime = getTime(); +} + +void DrasculaEngine::moveCharacters() { + int curPos[6]; + int r; + + if (characterMoved == 1 && stepX == STEP_X) { + for (r = 0; r < stepX; r++) { + if (currentChapter != 2) { + if (trackProtagonist == 0 && roomX - r == curX + curWidth / 2) { + characterMoved = 0; + stepX = STEP_X; + stepY = STEP_Y; + } + if (trackProtagonist == 1 && roomX + r == curX + curWidth / 2) { + characterMoved = 0; + stepX = STEP_X; + stepY = STEP_Y; + curX = roomX - curWidth / 2; + curY = roomY - curHeight; + } + } else if (currentChapter == 2) { + if (trackProtagonist == 0 && roomX - r == curX) { + characterMoved = 0; + stepX = STEP_X; + stepY = STEP_Y; + } + if (trackProtagonist == 1 && roomX + r == curX + curWidth) { + characterMoved = 0; + stepX = STEP_X; + stepY = STEP_Y; + curX = roomX - curWidth + 4; + curY = roomY - curHeight; + } + } + } + } + if (characterMoved == 1 && stepY == STEP_Y) { + for (r = 0; r < stepY; r++) { + if (trackProtagonist == 2 && roomY - r == curY + curHeight) { + characterMoved = 0; + stepX = STEP_X; + stepY = STEP_Y; + } + if (trackProtagonist == 3 && roomY + r == curY + curHeight) { + characterMoved = 0; + stepX = STEP_X; + stepY = STEP_Y; + } + } + } + + if (currentChapter == 1 || currentChapter == 4 || currentChapter == 5 || currentChapter == 6) { + if (hare_se_ve == 0) { + increaseFrameNum(); + return; + } + } + + if (characterMoved == 0) { + curPos[0] = 0; + curPos[1] = DIF_MASK_HARE; + curPos[2] = curX; + curPos[3] = curY; + if (currentChapter == 2) { + curPos[4] = curWidth; + curPos[5] = curHeight; + } else { + curPos[4] = CHARACTER_WIDTH; + curPos[5] = CHARACTER_HEIGHT; + } + + if (trackProtagonist == 0) { + curPos[1] = 0; + if (currentChapter == 2) + copyRectClip(curPos, extraSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], extraSurface, screenSurface); + } else if (trackProtagonist == 1) { + if (currentChapter == 2) + copyRectClip(curPos, extraSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], extraSurface, screenSurface); + } else if (trackProtagonist == 2) { + if (currentChapter == 2) + copyRectClip(curPos, backSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], backSurface, screenSurface); + } else { + if (currentChapter == 2) + copyRectClip(curPos, frontSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], frontSurface, screenSurface); + } + } else if (characterMoved == 1) { + curPos[0] = _frameX[num_frame]; + curPos[1] = frame_y + DIF_MASK_HARE; + curPos[2] = curX; + curPos[3] = curY; + if (currentChapter == 2) { + curPos[4] = curWidth; + curPos[5] = curHeight; + } else { + curPos[4] = CHARACTER_WIDTH; + curPos[5] = CHARACTER_HEIGHT; + } + if (trackProtagonist == 0) { + curPos[1] = 0; + if (currentChapter == 2) + copyRectClip(curPos, extraSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], extraSurface, screenSurface); + } else if (trackProtagonist == 1) { + if (currentChapter == 2) + copyRectClip(curPos, extraSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], extraSurface, screenSurface); + } else if (trackProtagonist == 2) { + if (currentChapter == 2) + copyRectClip(curPos, backSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], backSurface, screenSurface); + } else { + if (currentChapter == 2) + copyRectClip(curPos, frontSurface, screenSurface); + else + reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], + factor_red[curY + curHeight], frontSurface, screenSurface); + } + increaseFrameNum(); + } +} + +void DrasculaEngine::quadrant_1() { + float distanceX, distanceY; + + if (currentChapter == 2) + distanceX = curX - roomX; + else + distanceX = curX + curWidth / 2 - roomX; + + distanceY = (curY + curHeight) - roomY; + + if (distanceX < distanceY) { + curDirection = 0; + trackProtagonist = 2; + stepX = (int)(distanceX / (distanceY / STEP_Y)); + } else { + curDirection = 7; + trackProtagonist = 0; + stepY = (int)(distanceY / (distanceX / STEP_X)); + } +} + +void DrasculaEngine::quadrant_2() { + float distanceX, distanceY; + + if (currentChapter == 2) + distanceX = abs(curX + curWidth - roomX); + else + distanceX = abs(curX + curWidth / 2 - roomX); + + distanceY = (curY + curHeight) - roomY; + + if (distanceX < distanceY) { + curDirection = 1; + trackProtagonist = 2; + stepX = (int)(distanceX / (distanceY / STEP_Y)); + } else { + curDirection = 2; + trackProtagonist = 1; + stepY = (int)(distanceY / (distanceX / STEP_X)); + } +} + +void DrasculaEngine::quadrant_3() { + float distanceX, distanceY; + + if (currentChapter == 2) + distanceX = curX - roomX; + else + distanceX = curX + curWidth / 2 - roomX; + + distanceY = roomY - (curY + curHeight); + + if (distanceX < distanceY) { + curDirection = 5; + trackProtagonist = 3; + stepX = (int)(distanceX / (distanceY / STEP_Y)); + } else { + curDirection = 6; + trackProtagonist = 0; + stepY = (int)(distanceY / (distanceX / STEP_X)); + } +} + +void DrasculaEngine::quadrant_4() { + float distanceX, distanceY; + + if (currentChapter == 2) + distanceX = abs(curX + curWidth - roomX); + else + distanceX = abs(curX + curWidth / 2 - roomX); + + distanceY = roomY - (curY + curHeight); + + if (distanceX < distanceY) { + curDirection = 4; + trackProtagonist = 3; + stepX = (int)(distanceX / (distanceY / STEP_Y)); + } else { + curDirection = 3; + trackProtagonist = 1; + stepY = (int)(distanceY / (distanceX / STEP_X)); + } +} + +void DrasculaEngine::increaseFrameNum() { + timeDiff = getTime() - startTime; + + if (timeDiff >= 6) { + startTime = getTime(); + num_frame++; + if (num_frame == 6) + num_frame = 0; + + if (curDirection == 0 || curDirection == 7) { + curX -= stepX; + curY -= stepY; + } else if (curDirection == 1 || curDirection == 2) { + curX += stepX; + curY -= stepY; + } else if (curDirection == 3 || curDirection == 4) { + curX += stepX; + curY += stepY; + } else if (curDirection == 5 || curDirection == 6) { + curX -= stepX; + curY += stepY; + } + } + + if (currentChapter != 2) { + curY += (int)(curHeight - newHeight); + curX += (int)(curWidth - newWidth); + curHeight = (int)newHeight; + curWidth = (int)newWidth; + } +} + +void DrasculaEngine::walkDown() { + curDirection = 4; + trackProtagonist = 3; + stepX = 0; +} + +void DrasculaEngine::walkUp() { + curDirection = 0; + trackProtagonist = 2; + stepX = 0; +} + +void DrasculaEngine::moveVonBraun() { + int pos_vb[6]; + + if (vonBraunHasMoved == 0) { + pos_vb[0] = 256; + pos_vb[1] = 129; + pos_vb[2] = vonBraunX; + pos_vb[3] = 66; + pos_vb[4] = 33; + pos_vb[5] = 69; + if (trackVonBraun == 0) + pos_vb[0] = 222; + else if (trackVonBraun == 1) + pos_vb[0] = 188; + } else { + pos_vb[0] = actorFrames[kFrameVonBraun]; + pos_vb[1] = (trackVonBraun == 0) ? 62 : 131; + pos_vb[2] = vonBraunX; + pos_vb[3] = 66; + pos_vb[4] = 28; + pos_vb[5] = 68; + + actorFrames[kFrameVonBraun] += 29; + if (actorFrames[kFrameVonBraun] > 146) + actorFrames[kFrameVonBraun] = 1; + } + + copyRectClip(pos_vb, frontSurface, screenSurface); +} + +void DrasculaEngine::placeVonBraun(int pointX) { + trackVonBraun = (pointX < vonBraunX) ? 0 : 1; + vonBraunHasMoved = 1; + + for (;;) { + updateRoom(); + updateScreen(); + if (trackVonBraun == 0) { + vonBraunX = vonBraunX - 5; + if (vonBraunX <= pointX) + break; + } else { + vonBraunX = vonBraunX + 5; + if (vonBraunX >= pointX) + break; + } + pause(5); + } + + vonBraunHasMoved = 0; +} + + + +} // End of namespace Drascula diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 8ae6a18b3a..feb6cb93ca 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -27,125 +27,140 @@ namespace Drascula { -static const int interf_x[] ={ 1, 65, 129, 193, 1, 65, 129 }; -static const int interf_y[] ={ 51, 51, 51, 51, 83, 83, 83 }; +void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int height, int count, byte* src, int delayVal) { + int x = 0; + for (int n = 0; n < count; n++){ + x++; + copyBackground(x, y, destX, destY, width, height, src, screenSurface); + updateScreen(destX, destY, destX, destY, width, height, screenSurface); + x += width; + pause(delayVal); + } +} + +void DrasculaEngine::updateAnim2(int y, int px, int py, int width, int height, int count, byte* src) { + int x = 0; + + for (int n = 0; n < count; n++) { + x++; + copyBackground(px, py, px, py, width, height, bgSurface, screenSurface); + copyRect(x, y, px, py, width, height, src, screenSurface); + updateScreen(px, py, px, py, width, height, screenSurface); + x = x + width; + pause(3); + } +} + +// This is the game's introduction sequence void DrasculaEngine::animation_1_1() { int l, l2, p; - int pos_pixel[6]; + int pixelPos[6]; while (term_int == 0) { - playmusic(29); - fliplay("logoddm.bin", 9); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playMusic(29); + playFLI("logoddm.bin", 9); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; delay(600); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); delay(340); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - playmusic(26); + playMusic(26); delay(500); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - fliplay("logoalc.bin", 8); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playFLI("logoalc.bin", 8); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - loadPic("cielo.alg"); - decompressPic(dir_zona_pantalla, 256); - Negro(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - FundeDelNegro(2); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic("cielo.alg", screenSurface, COMPLETE_PAL); + black(); + updateScreen(); + fadeFromBlack(2); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; delay(900); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - color_abc(ROJO); - centra_texto("Transilvanya, 1993 d.c.", 160, 100); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + color_abc(kColorRed); + centerText(_textmisc[_lang][1], 160, 100); + updateScreen(); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; delay(1000); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; delay(1200); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - fliplay("scrollb.bin", 9); + playFLI("scrollb.bin", 9); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - comienza_sound("s5.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playSound(5); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("scr2.bin", 17); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("scr2.bin", 17)) break; - fin_sound_corte(); - anima("scr3.bin", 17); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + stopSound(); + if (animate("scr3.bin", 17)) break; - loadPic("cielo2.alg"); - decompressPic(dir_zona_pantalla, 256); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic("cielo2.alg", screenSurface, COMPLETE_PAL); + updateScreen(); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - FundeAlNegro(1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + fadeToBlack(1); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("103.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("104.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("aux104.alg"); - decompressPic(dir_dibujo2, 1); + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(103, bgSurface, HALF_PAL); + loadPic(104, drawSurface3); + loadPic("aux104.alg", drawSurface2); - playmusic(4); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playMusic(4); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; delay(400); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; for (l2 = 0; l2 < 3; l2++) for (l = 0; l < 7; l++) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyBackground(interf_x[l], interf_y[l], 156, 45, 63, 31, dir_dibujo2, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if (getscan() == Common::KEYCODE_ESCAPE) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyBackground(interf_x[l], interf_y[l], 156, 45, 63, 31, drawSurface2, screenSurface); + updateScreen(); + if (getScan() == Common::KEYCODE_ESCAPE) { term_int = 1; break; } pause(3); } - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; l2 = 0; p = 0; - pos_pixel[3] = 45; - pos_pixel[4] = 63; - pos_pixel[5] = 31; + pixelPos[3] = 45; + pixelPos[4] = 63; + pixelPos[5] = 31; for (l = 0; l < 180; l++) { - copyBackground(0, 0, 320 - l, 0, l, 200, dir_dibujo3, dir_zona_pantalla); - copyBackground(l, 0, 0, 0, 320 - l, 200, dir_dibujo1, dir_zona_pantalla); + copyBackground(0, 0, 320 - l, 0, l, 200, drawSurface3, screenSurface); + copyBackground(l, 0, 0, 0, 320 - l, 200, bgSurface, screenSurface); - pos_pixel[0] = interf_x[l2]; - pos_pixel[1] = interf_y[l2]; - pos_pixel[2] = 156 - l; + pixelPos[0] = interf_x[l2]; + pixelPos[1] = interf_y[l2]; + pixelPos[2] = 156 - l; - copyRectClip(pos_pixel, dir_dibujo2, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRectClip(pixelPos, drawSurface2, screenSurface); + updateScreen(); p++; if (p == 6) { p = 0; @@ -153,1559 +168,1212 @@ void DrasculaEngine::animation_1_1() { } if (l2 == 7) l2 = 0; - if (getscan() == Common::KEYCODE_ESCAPE) { + if (getScan() == Common::KEYCODE_ESCAPE) { term_int = 1; break; } } - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - copyBackground(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1); + copyBackground(0, 0, 0, 0, 320, 200, screenSurface, bgSurface); - talk_dr_grande(_textd[_lang][1], "D1.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_dr_grande(1); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - loadPic("100.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("auxigor.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("auxdr.alg"); - decompressPic(dir_hare_fondo, 1); - sentido_dr = 0; - x_dr = 129; - y_dr = 95; - sentido_igor = 1; - x_igor = 66; - y_igor = 97; - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk_igor_dch(_texti[_lang][8], "I8.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk_dr_izq(_textd[_lang][2], "d2.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - talk_dr_izq(_textd[_lang][3], "d3.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - anima("lib.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - anima("lib2.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic(100, bgSurface, HALF_PAL); + loadPic("auxigor.alg", frontSurface); + loadPic("auxdr.alg", backSurface); + trackDrascula = 0; + drasculaX = 129; + drasculaY = 95; + trackIgor = 1; + igorX = 66; + igorY = 97; + + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); + talk_igor(8, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); + talk_drascula(2); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + talk_drascula(3); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + if (animate("lib.bin", 16)) + break; + if (animate("lib2.bin", 16)) break; clearRoom(); - color_solo = ROJO; - loadPic("plan1.alg"); - decompressPic(dir_zona_pantalla, MEDIA); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + color_solo = kColorRed; + loadPic("plan1.alg", screenSurface, HALF_PAL); + updateScreen(); pause(10); talk_solo(_textd[_lang][4],"d4.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - loadPic("plan1.alg"); - decompressPic(dir_zona_pantalla, MEDIA); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("plan1.alg", screenSurface, HALF_PAL); + updateScreen(); talk_solo(_textd[_lang][5], "d5.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("lib2.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("lib2.bin", 16)) break; clearRoom(); - loadPic("plan2.alg"); - decompressPic(dir_zona_pantalla, MEDIA); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("plan2.alg", screenSurface, HALF_PAL); + updateScreen(); pause(20); talk_solo(_textd[_lang][6], "d6.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("lib2.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("lib2.bin", 16)) break; clearRoom(); - loadPic("plan3.alg"); - decompressPic(dir_zona_pantalla, MEDIA); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("plan3.alg", screenSurface, HALF_PAL); + updateScreen(); pause(20); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; talk_solo(_textd[_lang][7], "d7.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - loadPic("plan3.alg"); - decompressPic(dir_zona_pantalla, MEDIA); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("plan3.alg", screenSurface, HALF_PAL); + updateScreen(); talk_solo(_textd[_lang][8], "d8.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - loadPic("100.alg"); - decompressPic(dir_dibujo1, MEDIA); + loadPic(100, bgSurface, HALF_PAL); MusicFadeout(); - stopmusic(); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + stopMusic(); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_igor_dch(_texti[_lang][9], "I9.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_igor(9, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_dr_izq(_textd[_lang][9], "d9.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_drascula(9); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_igor_dch(_texti[_lang][10], "I10.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_igor(10, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - playmusic(11); - talk_dr_izq(_textd[_lang][10], "d10.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playMusic(11); + talk_drascula(10); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("rayo1.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("rayo1.bin", 16)) break; - comienza_sound("s5.als"); - anima("rayo2.bin", 15); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playSound(5); + if (animate("rayo2.bin", 15)) break; - anima("frel2.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("frel2.bin", 16)) break; - anima("frel.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("frel.bin", 16)) break; - anima("frel.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("frel.bin", 16)) break; - fin_sound_corte(); + stopSound(); clearRoom(); - Negro(); - playmusic(23); - FundeDelNegro(0); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - sentido_dr = 1; - talk_igor_dch(_texti[_lang][1], "I1.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - talk_dr_dch(_textd[_lang][11], "d11.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - sentido_dr = 3; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + black(); + playMusic(23); + fadeFromBlack(0); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + trackDrascula = 1; + talk_igor(1, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + talk_drascula(11, 1); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + trackDrascula = 3; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); pause(1); - sentido_dr = 0; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk_dr_izq(_textd[_lang][12], "d12.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - sentido_dr = 3; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + trackDrascula = 0; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); + talk_drascula(12); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + trackDrascula = 3; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); pause(1); - sentido_dr = 1; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk_igor_dch(_texti[_lang][2], "I2.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + trackDrascula = 1; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); + talk_igor(2, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; pause(13); - talk_dr_dch(_textd[_lang][13],"d13.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) - break; - sentido_dr = 3; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + talk_drascula(13, 1); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) + break; + trackDrascula = 3; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); pause(1); - sentido_dr = 0; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk_dr_izq(_textd[_lang][14], "d14.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + trackDrascula = 0; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + updateScreen(); + talk_drascula(14); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_igor_dch(_texti[_lang][3], "I3.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_igor(3, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_dr_izq(_textd[_lang][15], "d15.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_drascula(15); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_igor_dch(_texti[_lang][4], "I4.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_igor(4, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_dr_izq(_textd[_lang][16], "d16.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_drascula(16); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_igor_dch(_texti[_lang][5], "I5.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_igor(5, kIgorDch); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - sentido_igor = 3; - talk_dr_izq(_textd[_lang][17], "d17.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + trackIgor = 3; + talk_drascula(17); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; pause(18); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_igor_frente(_texti[_lang][6], "I6.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_igor(6, kIgorFront); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - FundeAlNegro(0); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + fadeToBlack(0); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - playmusic(2); + playMusic(2); pause(5); - fliplay("intro.bin", 12); + playFLI("intro.bin", 12); term_int = 1; } clearRoom(); - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); -} - -void DrasculaEngine::talk_dr_grande(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - int x_talk[4] = {47, 93, 139, 185}; - int cara; - int l = 0; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(ROJO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(3); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyBackground(interf_x[l] + 24, interf_y[l], 0, 45, 39, 31, dir_dibujo2, dir_zona_pantalla); - copyBackground(x_talk[cara], 1, 171, 68, 45, 48, dir_dibujo2, dir_zona_pantalla); - l++; - if (l == 7) - l = 0; - - if (con_voces == 0) - centra_texto(dicho, 191, 69); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - byte key = getscan(); - if (key == Common::KEYCODE_ESCAPE) - term_int = 1; - - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(99, backSurface); } +// John falls in love with BJ, who is then abducted by Drascula void DrasculaEngine::animation_2_1() { int l; - lleva_al_hare(231, 91); + gotoObject(231, 91); hare_se_ve = 0; term_int = 0; for (;;) { - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("ag.bin", 14); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("ag.bin", 14)) break; - loadPic("an11y13.alg"); - decompressPic(dir_hare_dch, 1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (_lang == kSpanish) + textSurface = frontSurface; + + loadPic("an11y13.alg", extraSurface); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_tabernero(_textt[_lang][22], "T22.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_bartender(22); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (_lang == kSpanish) + textSurface = extraSurface; + + loadPic(97, extraSurface); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; pause(4); - comienza_sound("s1.als"); - hipo(18); - fin_sound(); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playSound(1); + hiccup(18); + finishSound(); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - stopmusic(); - corta_musica = 1; - memset(dir_zona_pantalla, 0, 64000); - color_solo = BLANCO; + stopMusic(); + musicStopped = 1; + memset(screenSurface, 0, 64000); + color_solo = kColorWhite; pause(80); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; talk_solo(_textbj[_lang][1], "BJ1.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - loadPic("bj.alg"); - decompressPic(dir_zona_pantalla, MEDIA); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic("bj.alg", screenSurface, HALF_PAL); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - Negro(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - FundeDelNegro(1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + black(); + updateScreen(); + fadeFromBlack(1); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - color_solo = AMARILLO; + color_solo = kColorYellow; talk_solo(_text[_lang][214], "214.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; clearRoom(); - loadPic("16.alg"); - decompressPic(dir_dibujo1, MEDIA); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic(16, bgSurface, HALF_PAL); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - loadPic("auxbj.alg"); - decompressPic(dir_dibujo3, 1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic("auxbj.alg", drawSurface3); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - strcpy(num_room, "16.alg"); + roomNumber = 16; - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; for (l = 0; l < 200; l++) factor_red[l] = 99; - x_bj = 170; - y_bj = 90; - sentido_bj = 0; - hare_x = 91; - hare_y = 95; - sentido_hare = 1; + bjX = 170; + bjY = 90; + trackBJ = 0; + curX = 91; + curY = 95; + trackProtagonist = 1; hare_se_ve = 1; - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - loadPic("97g.alg"); - decompressPic(dir_hare_dch, 1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + loadPic("97g.alg", extraSurface); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("lev.bin", 15); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("lev.bin", 15)) break; - lleva_al_hare(100 + ancho_hare / 2, 99 + alto_hare); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + gotoObject(100 + curWidth / 2, 99 + curHeight); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - sentido_hare = 1; - hare_x = 100; - hare_y = 95; + trackProtagonist = 1; + curX = 100; + curY = 95; - talk_bj(_textbj[_lang][2], "BJ2.als"); - talk(_text[_lang][215], "215.als"); - talk_bj(_textbj[_lang][3], "BJ3.als"); - talk(_text[_lang][216], "216.als"); - talk_bj(_textbj[_lang][4], "BJ4.als"); - talk_bj(_textbj[_lang][5], "BJ5.als"); - talk_bj(_textbj[_lang][6], "BJ6.als"); - talk(_text[_lang][217], "217.als"); - talk_bj(_textbj[_lang][7], "BJ7.als"); - talk(_text[_lang][218], "218.als"); - talk_bj(_textbj[_lang][8], "BJ8.als"); - talk(_text[_lang][219], "219.als"); - talk_bj(_textbj[_lang][9], "BJ9.als"); - talk(_text[_lang][220], "220.als"); - talk(_text[_lang][221], "221.als"); - talk_bj(_textbj[_lang][10], "BJ10.als"); - talk(_text[_lang][222], "222.als"); - anima("gaf.bin", 15); - anima("bjb.bin", 14); - playmusic(9); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_bj(2); + talk(215); + talk_bj(3); + talk(216); + talk_bj(4); + talk_bj(5); + talk_bj(6); + talk(217); + talk_bj(7); + talk(218); + talk_bj(8); + talk(219); + talk_bj(9); + talk(220); + talk(221); + talk_bj(10); + talk(222); + if (animate("gaf.bin", 15)) break; - loadPic("97.alg"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("bjb.bin", 14)) break; - decompressPic(dir_hare_dch, 1); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playMusic(9); + loadPic(97, extraSurface); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + updateScreen(); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; pause(120); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; talk_solo(_text[_lang][223], "223.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - color_solo = BLANCO; + color_solo = kColorWhite; updateRoom(); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(110); talk_solo(_textbj[_lang][11], "BJ11.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; updateRoom(); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + updateScreen(); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; pause(118); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - lleva_al_hare(132, 97 + alto_hare); + gotoObject(132, 97 + curHeight); pause(60); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk(_text[_lang][224], "224.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk(224); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk_bj(_textbj[_lang][12], "BJ12.als"); - lleva_al_hare(157, 98 + alto_hare); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + talk_bj(12); + gotoObject(157, 98 + curHeight); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - anima("bes.bin", 16); - playmusic(11); - anima("rap.bin", 16); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if (animate("bes.bin", 16)) break; - sentido_hare = 3; - strcpy(num_room, "no_bj.alg"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + playMusic(11); + if (animate("rap.bin", 16)) + break; + trackProtagonist = 3; + // The room number was originally changed here to "no_bj.alg", + // which doesn't exist. In reality, this was just a hack to + // set the room number to a non-existant one, so that BJ does + // not appear again when the room is refreshed after the + // animation where Count Drascula abducts her. We set the + // room number to -1 for the same purpose + // Also check animation_9_6(), where the same hack was used by + // the original + roomNumber = -1; + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; pause(8); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk(_text[_lang][225], "225.als"); + updateScreen(); + talk(225); pause(76); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - sentido_hare = 1; + trackProtagonist = 1; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk(_text[_lang][226], "226.als"); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + updateScreen(); + talk(226); + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(30); - if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE)) + if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)) break; - talk(_text[_lang][227],"227.als"); - FundeAlNegro(0); + talk(227); + fadeToBlack(0); break; } } void DrasculaEngine::animation_3_1() { - loadPic("an11y13.alg"); - decompressPic(dir_hare_dch, 1); - - talk(_text[_lang][192], "192.als"); - talk_tabernero(_textt[_lang][1], "t1.als"); - talk(_text[_lang][193], "193.als"); - talk_tabernero(_textt[_lang][2], "t2.als"); - talk(_text[_lang][194], "194.als"); - talk_tabernero(_textt[_lang][3], "t3.als"); - talk(_text[_lang][195], "195.als"); - talk_tabernero(_textt[_lang][4], "t4.als"); - talk(_text[_lang][196], "196.als"); - talk_tabernero(_textt[_lang][5], "t5.als"); - talk_tabernero(_textt[_lang][6], "t6.als"); - talk(_text[_lang][197], "197.als"); - talk_tabernero(_textt[_lang][7], "t7.als"); - talk(_text[_lang][198], "198.als"); - talk_tabernero(_textt[_lang][8], "t8.als"); - talk(_text[_lang][199], "199.als"); - talk_tabernero(_textt[_lang][9], "t9.als"); - talk(_text[_lang][200], "200.als"); - talk(_text[_lang][201], "201.als"); - talk(_text[_lang][202], "202.als"); + if (_lang == kSpanish) + textSurface = frontSurface; + + loadPic("an11y13.alg", extraSurface); + + talk(192); + talk_bartender(1); + talk(193); + talk_bartender(2); + talk(194); + talk_bartender(3); + talk(195); + talk_bartender(4); + talk(196); + talk_bartender(5); + talk_bartender(6); + talk(197); + talk_bartender(7); + talk(198); + talk_bartender(8); + talk(199); + talk_bartender(9); + talk(200); + talk(201); + talk(202); flags[0] = 1; - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); + if (_lang == kSpanish) + textSurface = extraSurface; + + loadPic(97, extraSurface); } void DrasculaEngine::animation_4_1() { - loadPic("an12.alg"); - decompressPic(dir_hare_dch, 1); + if (_lang == kSpanish) + textSurface = frontSurface; + + loadPic("an12.alg", extraSurface); - talk(_text[_lang][205],"205.als"); + talk(205); updateRefresh_pre(); - copyBackground(1, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); - updateScreen(228,112, 228,112, 47,60, dir_zona_pantalla); + copyBackground(1, 139, 228, 112, 47, 60, extraSurface, screenSurface); + updateScreen(228,112, 228,112, 47,60, screenSurface); pause(3); updateRefresh_pre(); - copyBackground(49, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); - pon_hare(); + copyBackground(49, 139, 228, 112, 47, 60, extraSurface, screenSurface); + moveCharacters(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(3); - stopmusic(); + stopMusic(); flags[11] = 1; - talk_pianista(_textp[_lang][1], "p1.als"); - talk(_text[_lang][206], "206.als"); - talk_pianista(_textp[_lang][2], "p2.als"); - talk(_text[_lang][207], "207.als"); - talk_pianista(_textp[_lang][3], "p3.als"); - talk(_text[_lang][208], "208.als"); - talk_pianista(_textp[_lang][4], "p4.als"); - talk(_text[_lang][209], "209.als"); + talk_pianist(1); + talk(206); + talk_pianist(2); + talk(207); + talk_pianist(3); + talk(208); + talk_pianist(4); + talk(209); + + if (_lang == kSpanish) + textSurface = extraSurface; flags[11] = 0; - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); + loadPic(97, extraSurface); } void DrasculaEngine::animation_1_2() { - lleva_al_hare(178, 121); - lleva_al_hare(169, 135); + gotoObject(178, 121); + gotoObject(169, 135); } void DrasculaEngine::animation_2_2() { - int n, x=0; - - sentido_hare = 0; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_hare(); + trackProtagonist = 0; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + moveCharacters(); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - loadPic("an2_1.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("an2_2.alg"); - decompressPic(dir_hare_dch, 1); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyBackground(1, 1, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla); - updateScreen(201,87, 201,87, 50,52, dir_zona_pantalla); - x = x + 50; - pause(3); - } + updateScreen(); + loadPic("an2_1.alg", frontSurface); + loadPic("an2_2.alg", extraSurface); - x = 0; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyBackground(1, 1, 201, 87, 50, 52, frontSurface, screenSurface); + updateScreen(); - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 55, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla); - updateScreen(201, 87, 201, 87, 50, 52, dir_zona_pantalla); - x = x + 50; - pause(3); - } + updateAnim(1, 201, 87, 50, 52, 6, frontSurface); + updateAnim(55, 201, 87, 50, 52, 6, frontSurface); + updateAnim(109, 201, 87, 50, 52, 6, frontSurface); - x = 0; + playSound(2); - for (n = 0; n < 6; n++){ - x++; - copyBackground(x, 109, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla); - updateScreen(201, 87, 201, 87, 50, 52, dir_zona_pantalla); - x = x + 50; - pause(3); - } - - x = 0; - comienza_sound("s2.als"); - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 201, 87, 50, 52, dir_hare_dch, dir_zona_pantalla); - updateScreen(201,87, 201,87, 50,52, dir_zona_pantalla); - x = x + 50; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 55, 201, 87, 50, 52, dir_hare_dch, dir_zona_pantalla); - updateScreen(201, 87, 201, 87, 50, 52, dir_zona_pantalla); - x = x + 50; - pause(3); - } - x = 0; - - for (n = 0; n < 2; n++) { - x++; - copyBackground(x, 109, 201, 87, 50, 52, dir_hare_dch, dir_zona_pantalla); - updateScreen(201, 87, 201, 87, 50, 52, dir_zona_pantalla); - x = x + 50; - pause(3); - } + updateAnim(1, 201, 87, 50, 52, 6, extraSurface); + updateAnim(55, 201, 87, 50, 52, 6, extraSurface); + updateAnim(109, 201, 87, 50, 52, 2, extraSurface); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); - fin_sound(); + finishSound(); pause (4); - comienza_sound("s1.als"); + playSound(1); hipo_sin_nadie(12); - fin_sound(); + finishSound(); } void DrasculaEngine::animation_3_2() { - lleva_al_hare(163, 106); - lleva_al_hare(287, 101); - sentido_hare = 0; + gotoObject(163, 106); + gotoObject(287, 101); + trackProtagonist = 0; } void DrasculaEngine::animation_4_2() { - stopmusic(); + stopMusic(); flags[9] = 1; pause(12); - talk(_textd[_lang][56], "d56.als"); + talk(56); pause(8); clearRoom(); - loadPic("ciego1.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("ciego2.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("ciego3.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("ciego4.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("ciego5.alg"); - decompressPic(dir_hare_frente, 1); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("ciego1.alg", bgSurface, HALF_PAL); // ciego = blind + loadPic("ciego2.alg", drawSurface3); + loadPic("ciego3.alg", extraSurface); + loadPic("ciego4.alg", backSurface); + loadPic("ciego5.alg", frontSurface); + + if (_lang == kSpanish) + textSurface = frontSurface; + + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); pause(10); - talk_ciego(_textd[_lang][68], "d68.als", "44472225500022227555544444664447222550002222755554444466"); + talk_blind(1); pause(5); - talk_hacker(_textd[_lang][57], "d57.als"); + talk_hacker(57); pause(6); - talk_ciego(_textd[_lang][69],"d69.als","444722255000222275555444446655033336666664464402256555005504450005446"); + talk_blind(2); pause(4); - talk_hacker(_textd[_lang][58],"d58.als"); - talk_ciego(_textd[_lang][70],"d70.als", "4447222550002222755554444466550333226220044644550044755665500440006655556666655044744656550446470046"); + talk_hacker(58); + talk_blind(3); delay(14); - talk_hacker(_textd[_lang][59],"d59.als"); - talk_ciego(_textd[_lang][71],"d71.als", "550330227556444744446660004446655544444722255000222275555444446644444"); - talk_hacker(_textd[_lang][60],"d60.als"); - talk_ciego(_textd[_lang][72],"d72.als", "55033022755644455550444744400044504447222550002222755554444466000"); - talk_hacker(_textd[_lang][61],"d61.als"); - talk_ciego(_textd[_lang][73],"d73.als", "55033022755644444447227444466644444722255000222275555444446664404446554440055655022227500544446044444446"); - talk_hacker(_textd[_lang][62],"d62.als"); - talk_ciego(_textd[_lang][74],"d74.als", "55033022755644444472244472225500022227555544444662550002222755444446666055522275550005550022200222000222666"); - talk_hacker(_textd[_lang][63],"d63.als"); - talk_ciego(_textd[_lang][75],"d75.als", "44447774444555500222205550444444466666225266444755444722255000222275555444446633223220044022203336227555770550444660557220553302224477777550550550222635533000662220002275572227025555"); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - _system->delayMillis(1); - talk_hacker(_textd[_lang][64], "d64.als"); - talk_ciego(_textd[_lang][76], "d76.als", "5555500004445550330244472225500022227555544444662755644446666005204402266222003332222774440446665555005550335544444"); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + talk_hacker(59); + talk_blind(4); + talk_hacker(60); + talk_blind(5); + talk_hacker(61); + talk_blind(6); + talk_hacker(62); + talk_blind(7); + talk_hacker(63); + talk_blind(8); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); + _system->delayMillis(1000); + talk_hacker(64); + talk_blind(9); + + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); pause(14); clearRoom(); - playmusic(musica_room); - loadPic("9.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("aux9.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - sin_verbo(); + playMusic(roomMusic); + loadPic(9, bgSurface, HALF_PAL); + loadPic("aux9.alg", drawSurface3); + loadPic(96, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); + withoutVerb(); + + if (_lang == kSpanish) + textSurface = extraSurface; flags[9] = 0; flags[4] = 1; } void DrasculaEngine::animation_8_2() { - talk_pianista(_textp[_lang][6], "P6.als"); - talk(_text[_lang][358], "358.als"); - talk_pianista(_textp[_lang][7], "P7.als"); - talk_pianista(_textp[_lang][8], "P8.als"); + talk_pianist(6); + talk(358); + talk_pianist(7); + talk_pianist(8); } void DrasculaEngine::animation_9_2() { - talk_pianista(_textp[_lang][9], "P9.als"); - talk_pianista(_textp[_lang][10], "P10.als"); - talk_pianista(_textp[_lang][11], "P11.als"); + talk_pianist(9); + talk_pianist(10); + talk_pianist(11); } void DrasculaEngine::animation_10_2() { - talk_pianista(_textp[_lang][12], "P12.als"); - talk(_text[_lang][361], "361.als"); + talk_pianist(12); + talk(361); pause(40); - talk_pianista(_textp[_lang][13], "P13.als"); - talk(_text[_lang][362], "362.als"); - talk_pianista(_textp[_lang][14], "P14.als"); - talk(_text[_lang][363], "363.als"); - talk_pianista(_textp[_lang][15], "P15.als"); - talk(_text[_lang][364], "364.als"); - talk_pianista(_textp[_lang][16], "P16.als"); + talk_pianist(13); + talk(362); + talk_pianist(14); + talk(363); + talk_pianist(15); + talk(364); + talk_pianist(16); } void DrasculaEngine::animation_14_2() { - int n, pos_cabina[6]; + int cabinPos[6] = { 150, 6, 69, -160, 158, 161 }; int l = 0; - loadPic("an14_2.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an14_1.alg"); + loadPic("an14_2.alg", backSurface); - pos_cabina[0] = 150; - pos_cabina[1] = 6; - pos_cabina[2] = 69; - pos_cabina[3] = -160; - pos_cabina[4] = 158; - pos_cabina[5] = 161; - - for (n = -160; n <= 0; n = n + 5 + l) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + for (int n = -160; n <= 0; n = n + 5 + l) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - pon_hare(); - pon_vb(); - pos_cabina[3] = n; - copyRectClip(pos_cabina, dir_hare_fondo, dir_zona_pantalla); + moveCharacters(); + moveVonBraun(); + cabinPos[3] = n; + copyRectClip(cabinPos, backSurface, screenSurface); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - l = l + 1; + updateScreen(); + l++; } flags[24] = 1; - decompressPic(dir_dibujo1, 1); + memcpy(bgSurface, screenSurface, 64000); - comienza_sound("s7.als"); - hipo(15); + playSound(7); + hiccup(15); - fin_sound(); + finishSound(); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic(99, backSurface); } void DrasculaEngine::animation_15_2() { - talk_borracho(_textb[_lang][8], "B8.als"); + talk_drunk(8); pause(7); - talk_borracho(_textb[_lang][9], "B9.als"); - talk_borracho(_textb[_lang][10], "B10.als"); - talk_borracho(_textb[_lang][11], "B11.als"); + talk_drunk(9); + talk_drunk(10); + talk_drunk(11); } void DrasculaEngine::animation_16_2() { - int l; - - talk_borracho(_textb[_lang][12], "B12.als"); - talk(_text[_lang][371], "371.als"); + talk_drunk(12); + talk(371); clearRoom(); - playmusic(32); - int key = getscan(); + if (_lang == kSpanish) + playMusic(30); + else + playMusic(32); + + int key = getScan(); if (key != 0) goto asco; - color_abc(VERDE_OSCURO); + if (_lang != kSpanish) + color_abc(kColorDarkGreen); + + loadPic("his1.alg", bgSurface, HALF_PAL); - loadPic("his1.alg"); - decompressPic(dir_dibujo1, MEDIA); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - centra_texto(_texthis[_lang][1], 180, 180); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - key = getscan(); + if (_lang == kSpanish) + black(); + + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + + if (_lang != kSpanish) + centerText(_texthis[_lang][1], 180, 180); + + updateScreen(); + + if (_lang == kSpanish) + fadeFromBlack(1); + + key = getScan(); if (key != 0) goto asco; - _system->delayMillis(4); - key = getscan(); + if (_lang == kSpanish) + _system->delayMillis(3000); + else + _system->delayMillis(4000); + + key = getScan(); if (key != 0) goto asco; - FundeAlNegro(1); - key = getscan(); + fadeToBlack(1); + key = getScan(); if (key != 0) goto asco; clearRoom(); - loadPic("his2.alg"); - decompressPic(dir_dibujo1, MEDIA); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - centra_texto(_texthis[_lang][2], 180, 180); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - key = getscan(); + loadPic("his2.alg", bgSurface, HALF_PAL); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + + if (_lang != kSpanish) + centerText(_texthis[_lang][2], 180, 180); + + updateScreen(); + key = getScan(); if (key != 0) goto asco; - _system->delayMillis(4); - key = getscan(); + if (_lang == kSpanish) + _system->delayMillis(3000); + else + _system->delayMillis(4000); + + key = getScan(); if (key != 0) goto asco; - FundeAlNegro(1); - key = getscan(); + fadeToBlack(1); + key = getScan(); if (key != 0) goto asco; clearRoom(); - loadPic("his3.alg"); - decompressPic(dir_dibujo1, MEDIA); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - centra_texto(_texthis[_lang][3], 180, 180); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - key = getscan(); + loadPic("his3.alg", bgSurface, HALF_PAL); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + + if (_lang != kSpanish) + centerText(_texthis[_lang][3], 180, 180); + + updateScreen(); + key = getScan(); if (key != 0) goto asco; - _system->delayMillis(4); - key = getscan(); + if (_lang == kSpanish) + _system->delayMillis(3000); + else + _system->delayMillis(4000); + + key = getScan(); if (key != 0) goto asco; - FundeAlNegro(1); + fadeToBlack(1); clearRoom(); - loadPic("his4_1.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("his4_2.alg"); - decompressPic(dir_dibujo3, 1); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo3, dir_zona_pantalla); - centra_texto(_texthis[_lang][1], 180, 180); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - key = getscan(); + loadPic("his4_1.alg", bgSurface, HALF_PAL); + loadPic("his4_2.alg", drawSurface3); + + copyBackground(0, 0, 0, 0, 320, 200, drawSurface3, screenSurface); + + if (_lang != kSpanish) + centerText(_texthis[_lang][1], 180, 180); + + updateScreen(); + key = getScan(); if (key != 0) goto asco; - _system->delayMillis(4); - key = getscan(); + if (_lang == kSpanish) + _system->delayMillis(2000); + else + _system->delayMillis(4000); + + key = getScan(); if (key != 0) goto asco; - for (l = 1; l < 200; l++) { - copyBackground(0, 0, 0, l, 320, 200 - l, dir_dibujo3, dir_zona_pantalla); - copyBackground(0, 200 - l, 0, 0, 320, l, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - key = getscan(); + for (int l = 1; l < 200; l++) { + copyBackground(0, 0, 0, l, 320, 200 - l, drawSurface3, screenSurface); + copyBackground(0, 200 - l, 0, 0, 320, l, bgSurface, screenSurface); + updateScreen(); + key = getScan(); if (key != 0) goto asco; } pause(5); - FundeAlNegro(2); + fadeToBlack(2); clearRoom(); asco: - loadPic(roomDisk); - decompressPic(dir_dibujo3, 1); - loadPic(num_room); - decompressPic(dir_dibujo1, MEDIA); - Negro(); + loadPic(roomDisk, drawSurface3); + loadPic(roomNumber, bgSurface, HALF_PAL); + black(); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - FundeDelNegro(0); - if (musica_room != 0) - playmusic(musica_room); + updateScreen(); + fadeFromBlack(0); + if (roomMusic != 0) + playMusic(roomMusic); else - stopmusic(); + stopMusic(); } void DrasculaEngine::animation_17_2() { - talk_borracho(_textb[_lang][13], "B13.als"); - talk_borracho(_textb[_lang][14], "B14.als"); + talk_drunk(13); + talk_drunk(14); flags[40] = 1; } void DrasculaEngine::animation_19_2() { - talk_vbpuerta(_textvb[_lang][5], "VB5.als"); + talk_vonBraunpuerta(5); } void DrasculaEngine::animation_20_2() { - talk_vbpuerta(_textvb[_lang][7], "VB7.als"); - talk_vbpuerta(_textvb[_lang][8], "VB8.als"); - talk(_text[_lang][383], "383.als"); - talk_vbpuerta(_textvb[_lang][9], "VB9.als"); - talk(_text[_lang][384], "384.als"); - talk_vbpuerta(_textvb[_lang][10], "VB10.als"); - talk(_text[_lang][385], "385.als"); - talk_vbpuerta(_textvb[_lang][11], "VB11.als"); + talk_vonBraunpuerta(7); + talk_vonBraunpuerta(8); + talk(383); + talk_vonBraunpuerta(9); + talk(384); + talk_vonBraunpuerta(10); + talk(385); + talk_vonBraunpuerta(11); if (flags[23] == 0) { - talk(_text[_lang][350], "350.als"); - talk_vbpuerta(_textvb[_lang][57], "VB57.als"); + talk(350); + talk_vonBraunpuerta(57); } else { - talk(_text[_lang][386], "386.als"); - talk_vbpuerta(_textvb[_lang][12], "VB12.als"); + talk(386); + talk_vonBraunpuerta(12); flags[18] = 0; flags[14] = 1; - abre_puerta(15, 1); - sal_de_la_habitacion(1); + openDoor(15, 1); + exitRoom(1); animation_23_2(); - sal_de_la_habitacion(0); + exitRoom(0); flags[21] = 0; flags[24] = 0; - sentido_vb = 1; - vb_x = 120; + trackVonBraun = 1; + vonBraunX = 120; - rompo_y_salgo = 1; + breakOut = 1; } } void DrasculaEngine::animation_21_2() { - talk_vbpuerta(_textvb[_lang][6], "VB6.als"); + talk_vonBraunpuerta(6); } void DrasculaEngine::animation_23_2() { - loadPic("an24.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an24.alg", frontSurface); flags[21] = 1; if (flags[25] == 0) { - talk_vb(_textvb[_lang][13], "VB13.als"); - talk_vb(_textvb[_lang][14], "VB14.als"); + talk_vonBraun(13); + talk_vonBraun(14); pause(10); - talk(_text[_lang][387], "387.als"); + talk(387); } - talk_vb(_textvb[_lang][15], "VB15.als"); - lleva_vb(42); - sentido_vb = 1; - talk_vb(_textvb[_lang][16], "VB16.als"); - sentido_vb = 2; - lleva_al_hare(157, 147); - lleva_al_hare(131, 149); - sentido_hare = 0; + talk_vonBraun(15); + placeVonBraun(42); + trackVonBraun = 1; + talk_vonBraun(16); + trackVonBraun = 2; + gotoObject(157, 147); + gotoObject(131, 149); + trackProtagonist = 0; animation_14_2(); if (flags[25] == 0) - talk_vb(_textvb[_lang][17], "VB17.als"); + talk_vonBraun(17); pause(8); - sentido_vb = 1; - talk_vb(_textvb[_lang][18], "VB18.als"); + trackVonBraun = 1; + talk_vonBraun(18); if (flags[29] == 0) - animation_23_anexo(); + animation_23_joined(); else - animation_23_anexo2(); + animation_23_joined2(); - sentido_vb = 2; + trackVonBraun = 2; animation_25_2(); - lleva_vb(99); + placeVonBraun(99); if (flags[29] == 0) { - talk_vb(_textvb[_lang][19], "VB19.als"); + talk_vonBraun(19); if (flags[25] == 0) { - talk_vb(_textvb[_lang][20],"VB20.als"); - if (resta_objeto(7) == 0) + talk_vonBraun(20); + if (removeObject(kItemMoney) == 0) flags[30] = 1; - if (resta_objeto(18) == 0) + if (removeObject(kItemTwoCoins) == 0) flags[31] = 1; - if (resta_objeto(19) == 0) + if (removeObject(kItemOneCoin) == 0) flags[32] = 1; } - talk_vb(_textvb[_lang][21], "VB21.als"); + talk_vonBraun(21); } else animation_27_2(); flags[25] = 1; - rompo_y_salgo = 1; + breakOut = 1; } -void DrasculaEngine::animation_23_anexo() { - int n, p_x = hare_x + 2, p_y = hare_y - 3; +void DrasculaEngine::animation_23_joined() { + int p_x = curX + 2, p_y = curY - 3; int x[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260, 1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223}; int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 1, 1, 1, 1}; - loadPic("an23.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic("an23.alg", backSurface); - for (n = 0; n < 34; n++) { - copyRect(p_x, p_y, p_x, p_y, 36, 74, dir_dibujo1, dir_zona_pantalla); - copyRect(x[n], y[n], p_x, p_y, 36, 74, dir_hare_fondo, dir_zona_pantalla); + for (int n = 0; n < 34; n++) { + copyRect(p_x, p_y, p_x, p_y, 36, 74, bgSurface, screenSurface); + copyRect(x[n], y[n], p_x, p_y, 36, 74, backSurface, screenSurface); updateRefresh(); - updateScreen(p_x, p_y, p_x, p_y, 36, 74, dir_zona_pantalla); + updateScreen(p_x, p_y, p_x, p_y, 36, 74, screenSurface); pause(5); } - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic(99, backSurface); } -void DrasculaEngine::animation_23_anexo2() { - int n, p_x = hare_x + 4, p_y = hare_y; +void DrasculaEngine::animation_23_joined2() { + int p_x = curX + 4, p_y = curY; int x[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137}; int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73}; pause(50); - loadPic("an23_2.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic("an23_2.alg", backSurface); - for (n = 0; n < 14; n++) { - copyRect(p_x, p_y, p_x, p_y, 33, 71, dir_dibujo1, dir_zona_pantalla); - copyRect(x[n], y[n], p_x, p_y, 33, 71, dir_hare_fondo, dir_zona_pantalla); + for (int n = 0; n < 14; n++) { + copyRect(p_x, p_y, p_x, p_y, 33, 71, bgSurface, screenSurface); + copyRect(x[n], y[n], p_x, p_y, 33, 71, backSurface, screenSurface); updateRefresh(); - updateScreen(p_x,p_y, p_x,p_y, 33,71, dir_zona_pantalla); + updateScreen(p_x,p_y, p_x,p_y, 33,71, screenSurface); pause(5); } - loadPic("99.alg"); - decompressPic(dir_hare_fondo,1); + loadPic(99, backSurface); } void DrasculaEngine::animation_25_2() { - int n, pos_cabina[6]; + int cabinPos[6] = { 150, 6, 69, 0, 158, 161 }; - loadPic("an14_2.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("18.alg"); - decompressPic(dir_dibujo1, 1); - - pos_cabina[0] = 150; - pos_cabina[1] = 6; - pos_cabina[2] = 69; - pos_cabina[3] = 0; - pos_cabina[4] = 158; - pos_cabina[5] = 161; + loadPic("an14_2.alg", backSurface); + loadPic(18, bgSurface); flags[24] = 0; - comienza_sound("s6.als"); + playSound(6); - for (n = 0; n >= -160; n = n - 8) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + for (int n = 0; n >= -160; n = n - 8) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - pon_hare(); - pon_vb(); + moveCharacters(); + moveVonBraun(); - pos_cabina[3] = n; + cabinPos[3] = n; - copyRectClip(pos_cabina, dir_hare_fondo, dir_zona_pantalla); + copyRectClip(cabinPos, backSurface, screenSurface); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } - fin_sound(); + finishSound(); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic(99, backSurface); } void DrasculaEngine::animation_27_2() { flags[22] = 1; - sin_verbo(); - resta_objeto(23); - suma_objeto(11); + withoutVerb(); + removeObject(kItemEarWithEarPlug); + addObject(kItemEarplugs); - talk_vb(_textvb[_lang][23], "VB23.als"); - talk_vb(_textvb[_lang][24], "VB24.als"); + talk_vonBraun(23); + talk_vonBraun(24); if (flags[30] == 1) - suma_objeto(7); + addObject(kItemMoney); if (flags[31] == 1) - suma_objeto(18); + addObject(kItemTwoCoins); if (flags[32] == 1) - suma_objeto(19); - talk_vb(_textvb[_lang][25],"VB25.als"); - talk_vb(_textvb[_lang][26],"VB26.als"); + addObject(kItemOneCoin); + talk_vonBraun(25); + talk_vonBraun(26); } void DrasculaEngine::animation_28_2() { - talk_vb(_textvb[_lang][27], "VB27.als"); - talk_vb(_textvb[_lang][28], "VB28.als"); - talk_vb(_textvb[_lang][29], "VB29.als"); - talk_vb(_textvb[_lang][30], "VB30.als"); + for(int i = 27; i <= 30; i++) + talk_vonBraun(i); } void DrasculaEngine::animation_29_2() { if (flags[33] == 0) { - talk_vb(_textvb[_lang][32], "VB32.als"); - talk(_text[_lang][398], "398.als"); - talk_vb(_textvb[_lang][33], "VB33.als"); - talk(_text[_lang][399], "399.als"); - talk_vb(_textvb[_lang][34], "VB34.als"); - talk_vb(_textvb[_lang][35], "VB35.als"); - talk(_text[_lang][400], "400.als"); - talk_vb(_textvb[_lang][36], "VB36.als"); - talk_vb(_textvb[_lang][37], "VB37.als"); - talk(_text[_lang][386], "386.als"); - talk_vb(_textvb[_lang][38], "VB38.als"); - talk_vb(_textvb[_lang][39], "VB39.als"); - talk(_text[_lang][401], "401.als"); - talk_vb(_textvb[_lang][40], "VB40.als"); - talk_vb(_textvb[_lang][41], "VB41.als"); + talk_vonBraun(32); + talk(398); + talk_vonBraun(33); + talk(399); + talk_vonBraun(34); + talk_vonBraun(35); + talk(400); + talk_vonBraun(36); + talk_vonBraun(37); + talk(386); + talk_vonBraun(38); + talk_vonBraun(39); + talk(401); + talk_vonBraun(40); + talk_vonBraun(41); flags[33] = 1; } else - talk_vb(_textvb[_lang][43], "VB43.als"); + talk_vonBraun(43); - talk(_text[_lang][402], "402.als"); - talk_vb(_textvb[_lang][42], "VB42.als"); + talk(402); + talk_vonBraun(42); if (flags[38] == 0) { - talk(_text[_lang][403], "403.als"); - rompo_y_salgo = 1; + talk(403); + breakOut = 1; } else - talk(_text[_lang][386], "386.als"); + talk(386); } void DrasculaEngine::animation_30_2() { - talk_vb(_textvb[_lang][31], "VB31.als"); - talk(_text[_lang][396], "396.als"); + talk_vonBraun(31); + talk(396); } void DrasculaEngine::animation_31_2() { - talk_vb(_textvb[_lang][44], "VB44.als"); - lleva_vb(-50); + talk_vonBraun(44); + placeVonBraun(-50); pause(15); - lleva_al_hare(159, 140); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - sentido_hare = 2; + gotoObject(159, 140); + loadPic(99, backSurface); + trackProtagonist = 2; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(78); - sentido_hare = 0; + trackProtagonist = 0; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(22); - talk(_text[_lang][406], "406.als"); - lleva_vb(98); - talk_vb(_textvb[_lang][45], "VB45.als"); - talk_vb(_textvb[_lang][46], "VB46.als"); - talk_vb(_textvb[_lang][47], "VB47.als"); - talk(_text[_lang][407], "407.als"); - talk_vb(_textvb[_lang][48], "VB48.als"); - talk_vb(_textvb[_lang][49], "VB49.als"); - talk(_text[_lang][408], "408.als"); - talk_vb(_textvb[_lang][50], "VB50.als"); - talk_vb(_textvb[_lang][51], "VB51.als"); - talk(_text[_lang][409], "409.als"); - talk_vb(_textvb[_lang][52], "VB52.als"); - talk_vb(_textvb[_lang][53], "VB53.als"); + talk(406); + placeVonBraun(98); + talk_vonBraun(45); + talk_vonBraun(46); + talk_vonBraun(47); + talk(407); + talk_vonBraun(48); + talk_vonBraun(49); + talk(408); + talk_vonBraun(50); + talk_vonBraun(51); + talk(409); + talk_vonBraun(52); + talk_vonBraun(53); pause(12); - talk_vb(_textvb[_lang][54], "VB54.als"); - talk_vb(_textvb[_lang][55], "VB55.als"); - talk(_text[_lang][410], "410.als"); - talk_vb(_textvb[_lang][56], "VB56.als"); + talk_vonBraun(54); + talk_vonBraun(55); + talk(410); + talk_vonBraun(56); - rompo_y_salgo = 1; + breakOut = 1; flags[38] = 0; flags[36] = 1; - sin_verbo(); - resta_objeto(8); - resta_objeto(13); - resta_objeto(15); - resta_objeto(16); - resta_objeto(17); - suma_objeto(20); + withoutVerb(); + removeObject(kItemLeaves); + removeObject(kItemBubbleGum); + removeObject(kItemTissues); + removeObject(kItemCigarettes); + removeObject(kItemCandle); + addObject(kItemReefer); } void DrasculaEngine::animation_35_2() { - int n, x = 0; - - lleva_al_hare(96, 165); - lleva_al_hare(79, 165); + gotoObject(96, 165); + gotoObject(79, 165); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - loadPic("an35_1.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an35_2.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an35_1.alg", backSurface); + loadPic("an35_2.alg", frontSurface); - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 70, 90, 46, 80, dir_hare_fondo, dir_zona_pantalla); - updateScreen(70,90, 70,90, 46,80,dir_zona_pantalla); - x = x + 46; - pause(3); - } + updateAnim(1, 70, 90, 46, 80, 6, backSurface); + updateAnim(82, 70, 90, 46, 80, 6, backSurface); + updateAnim(1, 70, 90, 46, 80, 6, frontSurface); + updateAnim(82, 70, 90, 46, 80, 2, frontSurface); - x = 0; - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 82, 70, 90, 46, 80, dir_hare_fondo, dir_zona_pantalla); - updateScreen(70, 90, 70, 90, 46, 80, dir_zona_pantalla); - x = x + 46; - pause(3); - } + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - x = 0; - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 70, 90, 46, 80, dir_hare_frente, dir_zona_pantalla); - updateScreen(70, 90, 70, 90, 46, 80, dir_zona_pantalla); - - x = x + 46; - - pause(3); - } - - x = 0; - for (n = 0; n < 2; n++) { - x++; - copyBackground(x, 82, 70, 90, 46, 80, dir_hare_frente, dir_zona_pantalla); - updateScreen(70, 90, 70,90, 46, 80,dir_zona_pantalla); - x = x + 46; - pause(3); - } - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(19); - comienza_sound("s1.als"); + playSound(1); hipo_sin_nadie(18); - fin_sound(); + finishSound(); pause(10); - FundeAlNegro(2); + fadeToBlack(2); } void DrasculaEngine::animation_1_3() { - talk(_text[_lang][413], "413.als"); + talk(413); grr(); pause(50); - talk(_text[_lang][414], "414.als"); + talk(414); } void DrasculaEngine::animation_2_3() { flags[0] = 1; - playmusic(13); + playMusic(13); animation_3_3(); - playmusic(13); + playMusic(13); animation_4_3(); flags[1] = 1; updateRoom(); - updateScreen(120, 0, 120, 0, 200, 200, dir_zona_pantalla); + updateScreen(120, 0, 120, 0, 200, 200, screenSurface); animation_5_3(); flags[0] = 0; flags[1] = 1; - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic(96, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); - lleva_al_hare(332, 127); + gotoObject(332, 127); } void DrasculaEngine::animation_3_3() { - int n, x = 0; - int px = hare_x - 20, py = hare_y - 1; - - loadPic("an2y_1.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("an2y_2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("an2y_3.alg"); - decompressPic(dir_hare_fondo, 1); + int px = curX - 20, py = curY - 1; - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 2, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } + loadPic("an2y_1.alg", frontSurface); + loadPic("an2y_2.alg", extraSurface); + loadPic("an2y_3.alg", backSurface); - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 2, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 2, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } + updateAnim2(2, px, py, 71, 72, 4, frontSurface); + updateAnim2(75, px, py, 71, 72, 4, frontSurface); + updateAnim2(2, px, py, 71, 72, 4, extraSurface); + updateAnim2(75, px, py, 71, 72, 4, extraSurface); + updateAnim2(2, px, py, 71, 72, 4, backSurface); + updateAnim2(75, px, py, 71, 72, 4, backSurface); } void DrasculaEngine::animation_4_3() { - int n, x = 0; int px = 120, py = 63; - loadPic("any_1.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("any_2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("any_3.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic("any_1.alg", frontSurface); + loadPic("any_2.alg", extraSurface); + loadPic("any_3.alg", backSurface); - for (n = 0; n < 4; n++){ - x++; - copyBackground(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, px, py, 77, 89, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 77, 89, dir_zona_pantalla); - x = x + 77; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 91, px, py, 77, 89, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 77, 89, dir_zona_pantalla); - x = x + 77; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, px, py, 77, 89, dir_hare_dch, dir_zona_pantalla); - updateScreen(px, py, px, py, 77, 89, dir_zona_pantalla); - x = x + 77; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 91, px, py, 77, 89, dir_hare_dch, dir_zona_pantalla); - updateScreen(px, py, px, py, 77, 89, dir_zona_pantalla); - x = x + 77; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, px, py, 77, 89, dir_hare_fondo, dir_zona_pantalla); - updateScreen(px, py, px, py, 77, 89, dir_zona_pantalla); - x = x + 77; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 91, px, py, 77, 89, dir_hare_fondo, dir_zona_pantalla); - updateScreen(px, py, px, py, 77, 89, dir_zona_pantalla); - x = x + 77; - pause(3); - } + updateAnim2(1, px, py, 77, 89, 4, frontSurface); + updateAnim2(91, px, py, 77, 89, 4, frontSurface); + updateAnim2(1, px, py, 77, 89, 4, extraSurface); + updateAnim2(91, px, py, 77, 89, 4, extraSurface); + updateAnim2(1, px, py, 77, 89, 4, backSurface); + updateAnim2(91, px, py, 77, 89, 4, backSurface); } void DrasculaEngine::animation_5_3() { - int n, x = 0; - int px = hare_x - 20, py = hare_y - 1; - - loadPic("an3y_1.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("an3y_2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("an3y_3.alg"); - decompressPic(dir_hare_fondo, 1); - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 2, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 2, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla); - updateScreen(px,py, px,py, 71,72, dir_zona_pantalla); - x = x + 71; - pause(3); - } + int px = curX - 20, py = curY - 1; - x = 0; + loadPic("an3y_1.alg", frontSurface); + loadPic("an3y_2.alg", extraSurface); + loadPic("an3y_3.alg", backSurface); - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 2, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } - - x = 0; - - for (n = 0; n < 4; n++) { - x++; - copyBackground(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla); - updateScreen(px, py, px, py, 71, 72, dir_zona_pantalla); - x = x + 71; - pause(3); - } + updateAnim2(2, px, py, 71, 72, 4, frontSurface); + updateAnim2(75, px, py, 71, 72, 4, frontSurface); + updateAnim2(2, px, py, 71, 72, 4, extraSurface); + updateAnim2(75, px, py, 71, 72, 4, extraSurface); + updateAnim2(2, px, py, 71, 72, 4, backSurface); + updateAnim2(75, px, py, 71, 72, 4, backSurface); } void DrasculaEngine::animation_6_3() { @@ -1713,288 +1381,272 @@ void DrasculaEngine::animation_6_3() { int yoda_x[] = { 3 ,82, 161, 240, 3, 82 }; int yoda_y[] = { 3, 3, 3, 3, 94, 94 }; - hare_se_mueve = 0; + characterMoved = 0; flags[3] = 1; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); flags[1] = 0; - loadPic("an4y.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an4y.alg", frontSurface); for (frame = 0; frame < 6; frame++) { pause(3); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyRect(yoda_x[frame], yoda_y[frame], px, py, 78, 90, dir_hare_frente, dir_zona_pantalla); - updateScreen(px, py, px, py, 78, 90, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyRect(yoda_x[frame], yoda_y[frame], px, py, 78, 90, frontSurface, screenSurface); + updateScreen(px, py, px, py, 78, 90, screenSurface); } flags[2] = 1; - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); + loadPic(96, frontSurface); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::animation_rayo() { - loadPic("anr_1.alg"); - decompressPic(dir_hare_frente, MEDIA); - loadPic("anr_2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("anr_3.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("anr_4.alg"); - decompressPic(dir_dibujo1, 1); - loadPic("anr_5.alg"); - decompressPic(dir_dibujo3, 1); +void DrasculaEngine::animation_ray() { + loadPic("anr_1.alg", frontSurface, HALF_PAL); + loadPic("anr_2.alg", extraSurface); + loadPic("anr_3.alg", backSurface); + loadPic("anr_4.alg", bgSurface); + loadPic("anr_5.alg", drawSurface3); - updateScreen(0, 0, 0, 0, 320, 200, dir_hare_frente); + updateScreen(0, 0, 0, 0, 320, 200, frontSurface); pause(50); - comienza_sound("s5.als"); + playSound(5); - updateScreen(0, 0, 0, 0, 320, 200, dir_hare_dch); + updateScreen(0, 0, 0, 0, 320, 200, extraSurface); pause(3); - updateScreen(0, 0, 0, 0, 320, 200, dir_hare_fondo); + updateScreen(0, 0, 0, 0, 320, 200, backSurface); pause(3); - updateScreen(0, 0, 0, 0, 320, 200, dir_dibujo1); + updateScreen(0, 0, 0, 0, 320, 200, bgSurface); pause(3); - updateScreen(0, 0, 0, 0, 320, 200, dir_hare_fondo); + updateScreen(0, 0, 0, 0, 320, 200, backSurface); pause(3); - updateScreen(0, 0, 0, 0, 320, 200, dir_dibujo3); + updateScreen(0, 0, 0, 0, 320, 200, drawSurface3); pause(3); - updateScreen(0, 0, 0, 0, 320, 200, dir_hare_frente); - fin_sound(); + updateScreen(0, 0, 0, 0, 320, 200, frontSurface); + finishSound(); } void DrasculaEngine::animation_2_4() { - talk_igor_sentado(_texti[_lang][16], "I16.als"); - talk(_text[_lang][278], "278.als"); - talk_igor_sentado(_texti[_lang][17], "I17.als"); - talk(_text[_lang][279], "279.als"); - talk_igor_sentado(_texti[_lang][18], "I18.als"); + talk_igor(16, kIgorSeated); + talk(278); + talk_igor(17, kIgorSeated); + talk(279); + talk_igor(18, kIgorSeated); } void DrasculaEngine::animation_3_4() { - talk_igor_sentado(_texti[_lang][19], "I19.als"); - talk_igor_sentado(_texti[_lang][20], "I20.als"); - talk(_text[_lang][281], "281.als"); + talk_igor(19, kIgorSeated); + talk_igor(20, kIgorSeated); + talk(281); } void DrasculaEngine::animation_4_4() { - talk(_text[_lang][287], "287.als"); - talk_igor_sentado(_texti[_lang][21], "I21.als"); - talk(_text[_lang][284], "284.als"); - talk_igor_sentado(_texti[_lang][22], "I22.als"); - talk(_text[_lang][285], "285.als"); - talk_igor_sentado(_texti[_lang][23], "I23.als"); + talk(287); + talk_igor(21, kIgorSeated); + talk(284); + talk_igor(22, kIgorSeated); + talk(285); + talk_igor(23, kIgorSeated); } void DrasculaEngine::animation_7_4() { - Negro(); - talk(_text[_lang][427], "427.als"); - FundeDelNegro(1); - resta_objeto(8); - resta_objeto(10); - resta_objeto(12); - resta_objeto(16); - suma_objeto(17); + black(); + talk(427); + fadeFromBlack(1); + removeObject(8); + removeObject(10); + removeObject(12); + removeObject(16); + addObject(17); flags[30] = 0; flags[29] = 0; } void DrasculaEngine::animation_1_5() { if (flags[0] == 0) { - talk(_text[_lang][430], "430.als"); - talk_bj(_textbj[_lang][16], "BJ16.als"); - talk_bj(_textbj[_lang][17], "BJ17.als"); - talk_bj(_textbj[_lang][18], "BJ18.als"); - talk(_text[_lang][217], "217.als"); - talk_bj(_textbj[_lang][19], "BJ19.als"); - talk(_text[_lang][229], "229.als"); + talk(430); + talk_bj(16); + talk_bj(17); + talk_bj(18); + talk(217); + talk_bj(19); + talk(229); pause(5); - lleva_al_hare(114, 170); - sentido_hare = 3; - talk(_text[_lang][431], "431.als"); - talk_bj(_textbj[_lang][20], "BJ20.als"); - sentido_hare = 2; + gotoObject(114, 170); + trackProtagonist = 3; + talk(431); + talk_bj(20); + trackProtagonist = 2; pause(4); - talk(_text[_lang][438], "438.als"); - sitio_x = 120; - sitio_y = 157; - anda_a_objeto = 1; - sentido_final = 1; - empieza_andar(); - talk_bj(_textbj[_lang][21], "BJ21.als"); + talk(438); + roomX = 120; + roomY = 157; + walkToObject = 1; + trackFinal = 1; + startWalking(); + talk_bj(21); for (;;) { - if (hare_se_mueve == 0) + if (characterMoved == 0) break; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } - sentido_hare = 1; - talk(_text[_lang][229], "229.als"); + trackProtagonist = 1; + talk(229); flags[0] = 1; } - sentido_hare = 1; - conversa("op_8.cal"); + trackProtagonist = 1; + converse(8); } void DrasculaEngine::animation_2_5() { - talk_bj(_textbj[_lang][22], "BJ22.als"); + talk_bj(22); } void DrasculaEngine::animation_3_5() { - talk_bj(_textbj[_lang][23], "BJ23.als"); - agarra_objeto(10); - rompo_y_salgo = 1; + talk_bj(23); + pickObject(10); + breakOut = 1; } void DrasculaEngine::animation_4_5() { flags[7] = 1; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk(_text[_lang][228], "228.als"); - talk_lobo(_textl[_lang][1], "L1.als"); - talk_lobo(_textl[_lang][2], "L2.als"); + updateScreen(); + talk(228); + talk_werewolf(1); + talk_werewolf(2); pause(23); - talk(_text[_lang][229], "229.als"); - talk_lobo(_textl[_lang][3], "L3.als"); - talk_lobo(_textl[_lang][4], "L4.als"); - talk(_text[_lang][230], "230.als"); - talk_lobo(_textl[_lang][5], "L5.als"); - talk(_text[_lang][231], "231.als"); - talk_lobo(_textl[_lang][6], "L6.als"); - talk_lobo(_textl[_lang][7], "L7.als"); + talk(229); + talk_werewolf(3); + talk_werewolf(4); + talk(230); + talk_werewolf(5); + talk(231); + talk_werewolf(6); + talk_werewolf(7); pause(33); - talk(_text[_lang][232], "232.als"); - talk_lobo(_textl[_lang][8], "L8.als"); + talk(232); + talk_werewolf(8); } void DrasculaEngine::animation_5_5(){ int h; int frame = 0; - int hueso_x[] = {1, 99, 197, 1, 99, 197, 1, 99, 197}; - int hueso_y[] = {1, 1, 1, 66, 66, 66, 131, 131, 131}; - int vuela_x[] = {1, 63, 125, 187, 249}; - int pixel_x = hare_x - 53, pixel_y = hare_y - 9; + int boneX[] = {1, 99, 197, 1, 99, 197, 1, 99, 197}; + int boneY[] = {1, 1, 1, 66, 66, 66, 131, 131, 131}; + int flyX[] = {1, 63, 125, 187, 249}; + int pixelX = curX - 53, pixelY = curY - 9; - sin_verbo(); - resta_objeto(8); + withoutVerb(); + removeObject(8); - lleva_al_hare(hare_x - 19, hare_y + alto_hare); - sentido_hare = 1; + gotoObject(curX - 19, curY + curHeight); + trackProtagonist = 1; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - loadPic("3an5_1.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("3an5_2.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("3an5_1.alg", backSurface); + loadPic("3an5_2.alg", frontSurface); for (frame = 0; frame < 9; frame++) { pause(3); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyRect(hueso_x[frame], hueso_y[frame], pixel_x, pixel_y, 97, 64, dir_hare_fondo, dir_zona_pantalla); - updateScreen(pixel_x, pixel_y, pixel_x,pixel_y, 97,64, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, backSurface, screenSurface); + updateScreen(pixelX, pixelY, pixelX,pixelY, 97,64, screenSurface); } - copyBackground(52, 161, 198, 81, 26, 24, dir_dibujo3, dir_zona_pantalla); - updateScreen(198, 81, 198, 81, 26, 24, dir_zona_pantalla); + copyBackground(52, 161, 198, 81, 26, 24, drawSurface3, screenSurface); + updateScreen(198, 81, 198, 81, 26, 24, screenSurface); for (frame = 0; frame < 9; frame++) { pause(3); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyRect(hueso_x[frame], hueso_y[frame], pixel_x, pixel_y, 97, 64, dir_hare_frente, dir_zona_pantalla); - updateScreen(pixel_x, pixel_y, pixel_x,pixel_y, 97, 64, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, frontSurface, screenSurface); + updateScreen(pixelX, pixelY, pixelX,pixelY, 97, 64, screenSurface); } flags[6] = 1; - actualiza_datos(); + updateVisible(); pause(12); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); + loadPic(96, frontSurface); for (h = 0; h < (200 - 18); h++) - copyBackground(0, 53, 0, h, 320, 19, dir_hare_frente, dir_zona_pantalla); + copyBackground(0, 53, 0, h, 320, 19, frontSurface, screenSurface); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - loadPic("101.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("3an5_3.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("3an5_4.alg"); - decompressPic(dir_hare_dch, 1); + loadPic(101, bgSurface, HALF_PAL); + loadPic("3an5_3.alg", backSurface); + loadPic("3an5_4.alg", extraSurface); - updateScreen(0, 0, 0, 0, 320, 200, dir_dibujo1); + updateScreen(0, 0, 0, 0, 320, 200, bgSurface); pause(9); for (frame = 0; frame < 5; frame++) { pause(3); - copyBackground(vuela_x[frame], 1, 174, 79, 61, 109, dir_hare_fondo, dir_zona_pantalla); - updateScreen(174, 79, 174, 79, 61, 109, dir_zona_pantalla); + copyBackground(flyX[frame], 1, 174, 79, 61, 109, backSurface, screenSurface); + updateScreen(174, 79, 174, 79, 61, 109, screenSurface); } for (frame = 0; frame < 5; frame++) { pause(3); - copyBackground(vuela_x[frame], 1, 174, 79, 61, 109, dir_hare_dch, dir_zona_pantalla); - updateScreen(174, 79, 174, 79, 61, 109, dir_zona_pantalla); + copyBackground(flyX[frame], 1, 174, 79, 61, 109, extraSurface, screenSurface); + updateScreen(174, 79, 174, 79, 61, 109, screenSurface); } - updateScreen(0, 0, 0, 0, 320, 200, dir_dibujo1); + updateScreen(0, 0, 0, 0, 320, 200, bgSurface); - comienza_sound("s1.als"); - fin_sound(); + playSound(1); + finishSound(); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); + loadPic(99, backSurface); + loadPic(97, extraSurface); clearRoom(); - loadPic("49.alg"); - decompressPic(dir_dibujo1, MEDIA); + loadPic(49, bgSurface, HALF_PAL); } void DrasculaEngine::animation_6_5() { - talk_lobo(_textl[_lang][9], "L9.als"); - talk(_text[_lang][234], "234.als"); + talk_werewolf(9); + talk(234); } void DrasculaEngine::animation_7_5() { - talk_lobo(_textl[_lang][10], "L10.als"); - talk(_text[_lang][236], "236.als"); - talk_lobo(_textl[_lang][11], "L11.als"); - talk_lobo(_textl[_lang][12], "L12.als"); - talk_lobo(_textl[_lang][13], "L13.als"); + talk_werewolf(10); + talk(236); + talk_werewolf(11); + talk_werewolf(12); + talk_werewolf(13); pause(34); - talk_lobo(_textl[_lang][14], "L14.als"); + talk_werewolf(14); } void DrasculaEngine::animation_8_5() { - talk_lobo(_textl[_lang][15], "L15.als"); - talk(_text[_lang][238], "238.als"); - talk_lobo(_textl[_lang][16], "L16.als"); + talk_werewolf(15); + talk(238); + talk_werewolf(16); } void DrasculaEngine::animation_9_5() { flags[4] = 1; - talk(_text[_lang][401], "401.als"); - sin_verbo(); - resta_objeto(15); + talk(401); + withoutVerb(); + removeObject(15); } void DrasculaEngine::animation_10_5() { flags[3] = 1; - talk(_text[_lang][401], "401.als"); - sin_verbo(); - resta_objeto(12); + talk(401); + withoutVerb(); + removeObject(12); } void DrasculaEngine::animation_11_5() { @@ -2003,123 +1655,114 @@ void DrasculaEngine::animation_11_5() { animation_12_5(); else { flags[9] = 0; - talk(_text[_lang][33], "33.als"); + talk(33); } } void DrasculaEngine::animation_12_5() { - DacPalette256 palFondo1; - DacPalette256 palFondo2; - DacPalette256 palFondo3; + DacPalette256 bgPalette1; + DacPalette256 bgPalette2; + DacPalette256 bgPalette3; int frame; - const int rayo_x[] = {1, 46, 91, 136, 181, 226, 271, 181}; + const int rayX[] = {1, 46, 91, 136, 181, 226, 271, 181}; const int frusky_x[] = {100, 139, 178, 217, 100, 178, 217, 139, 100, 139}; const int elfrusky_x[] = {1, 68, 135, 1, 68, 135, 1, 68, 135, 68, 1, 135, 68, 135, 68}; - //const int humo_x[] = {1, 29, 57, 85, 113, 141, 169, 197, 225}; - int color, componente; - char fundido; + int color, component; + char fade; - playmusic(26); + playMusic(26); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(27); - anima("rayo1.bin", 23); - comienza_sound("s5.als"); - anima("rayo2.bin", 17); - sentido_hare = 1; + animate("rayo1.bin", 23); + playSound(5); + animate("rayo2.bin", 17); + trackProtagonist = 1; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - hare_oscuro(); + setDarkPalette(); for (color = 0; color < 255; color++) - for (componente = 0; componente < 3; componente++) { - palFondo1[color][componente] = palJuego[color][componente]; - palFondo2[color][componente] = palJuego[color][componente]; - palFondo3[color][componente] = palJuego[color][componente]; + for (component = 0; component < 3; component++) { + bgPalette1[color][component] = gamePalette[color][component]; + bgPalette2[color][component] = gamePalette[color][component]; + bgPalette3[color][component] = gamePalette[color][component]; } - for (fundido = 1; fundido >= 0; fundido--) { - for (color = 0; color < 128; color++) - for (componente = 0; componente < 3; componente++) - palFondo1[color][componente] = LimitaVGA(palFondo1[color][componente] - 8 + fundido); - } - - for (fundido = 2; fundido >= 0; fundido--) { - for (color = 0; color < 128; color++) - for (componente = 0; componente < 3; componente++) - palFondo2[color][componente] = LimitaVGA(palFondo2[color][componente] - 8 + fundido); - } - - for (fundido = 3; fundido >= 0; fundido--) { - for (color = 0; color < 128; color++) - for (componente = 0; componente < 3; componente++) - palFondo3[color][componente] = LimitaVGA(palFondo3[color][componente] - 8 + fundido); + for (fade = 3; fade >= 0; fade--) { + for (color = 0; color < 128; color++) { + for (component = 0; component < 3; component++) { + bgPalette3[color][component] = adjustToVGA(bgPalette3[color][component] - 8 + fade); + if (fade <= 2) + bgPalette2[color][component] = adjustToVGA(bgPalette2[color][component] - 8 + fade); + if (fade <= 1) + bgPalette1[color][component] = adjustToVGA(bgPalette1[color][component] - 8 + fade); + } + } } - loadPic("3an11_1.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic("3an11_1.alg", backSurface); for (frame = 0; frame < 8; frame++) { if (frame == 2 || frame == 4 || frame == 8 || frame==10) - setvgapalette256((byte *)&palFondo1); + setPalette((byte *)&bgPalette1); else if (frame == 1 || frame == 5 || frame == 7 || frame == 9) - setvgapalette256((byte *)&palFondo2); + setPalette((byte *)&bgPalette2); else - setvgapalette256((byte *)&palFondo3); + setPalette((byte *)&bgPalette3); pause(4); updateRoom(); - copyRect(rayo_x[frame], 1, 41, 0, 44, 44, dir_hare_fondo, dir_zona_pantalla); - copyRect(frusky_x[frame], 113, 205, 50, 38, 86, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRect(rayX[frame], 1, 41, 0, 44, 44, backSurface, screenSurface); + copyRect(frusky_x[frame], 113, 205, 50, 38, 86, drawSurface3, screenSurface); + updateScreen(); } - fin_sound_corte(); + stopSound(); for (frame = 0; frame < 15; frame++) { if (frame == 2 || frame == 4 || frame == 7 || frame == 9) - setvgapalette256((byte *)&palFondo1); + setPalette((byte *)&bgPalette1); else if (frame == 1 || frame == 5) - setvgapalette256((byte *)&palJuego); + setPalette((byte *)&gamePalette); else - setvgapalette256((byte *)&palFondo2); + setPalette((byte *)&bgPalette2); pause(4); updateRoom(); - copyRect(elfrusky_x[frame], 47, 192, 39, 66, 106, dir_hare_fondo, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRect(elfrusky_x[frame], 47, 192, 39, 66, 106, backSurface, screenSurface); + updateScreen(); } - anima("frel.bin", 16); + animate("frel.bin", 16); clearRoom(); - hare_claro(); - ActualizaPaleta(); + setBrightPalette(); + setPalette((byte *)&gamePalette); flags[1] = 1; animation_13_5(); - comienza_sound("s1.als"); - hipo(12); - fin_sound(); + playSound(1); + hiccup(12); + finishSound(); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic(99, backSurface); - lleva_al_hare(40, 169); - lleva_al_hare(-14, 175); + gotoObject(40, 169); + gotoObject(-14, 175); - rompo = 1; - musica_antes = musica_room; + doBreak = 1; + previousMusic = roomMusic; hare_se_ve = 1; clearRoom(); - sentido_hare = 1; - hare_se_mueve = 0; - hare_x = -1; - obj_saliendo = 104; - sin_verbo(); - carga_escoba("57.ald"); + trackProtagonist = 1; + characterMoved = 0; + curX = -1; + objExit = 104; + withoutVerb(); + enterRoom(57); } void DrasculaEngine::animation_13_5() { @@ -2127,38 +1770,31 @@ void DrasculaEngine::animation_13_5() { int frame = 0; int frus_x[] = {1, 46, 91, 136, 181, 226, 271}; int frus_y[] = {1, 1, 1, 1, 1, 1, 1, 89}; - int pos_frusky[6]; + int pos_frusky[6] = { 1, 1, frank_x, 81, 44, 87 }; - loadPic("auxfr.alg"); - decompressPic(dir_hare_fondo, 1); + loadPic("auxfr.alg", backSurface); - pos_frusky[3] = 81; - pos_frusky[4] = 44; - pos_frusky[5] = 87; - pos_frusky[0] = 1; - pos_frusky[1] = 1; - pos_frusky[2] = frank_x; updateRoom(); - copyRectClip(pos_frusky, dir_hare_fondo, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRectClip(pos_frusky, backSurface, screenSurface); + updateScreen(); pause(15); - playmusic(18); + playMusic(18); for (;;) { updateRoom(); pos_frusky[0] = frus_x[frame]; pos_frusky[1] = frus_y[frame]; pos_frusky[2] = frank_x; - copyRectClip( pos_frusky, dir_hare_fondo, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - frank_x = frank_x - 5; + copyRectClip( pos_frusky, backSurface, screenSurface); + updateScreen(); + frank_x -= 5; frame++; if (frank_x <= -45) break; if (frame == 7) { frame = 0; - sentido_hare = 3; + trackProtagonist = 3; } pause(6); } @@ -2166,153 +1802,143 @@ void DrasculaEngine::animation_13_5() { void DrasculaEngine::animation_14_5() { flags[11] = 1; - comienza_sound("s3.als"); + playSound(3); updateRoom(); - updateScreen(0, 0, 0,0 , 320, 200, dir_zona_pantalla); - fin_sound(); + updateScreen(0, 0, 0,0 , 320, 200, screenSurface); + finishSound(); pause(17); - sentido_hare = 3; - talk(_text[_lang][246],"246.als"); - lleva_al_hare(89, 160); + trackProtagonist = 3; + talk(246); + gotoObject(89, 160); flags[10] = 1; - comienza_sound("s7.als"); + playSound(7); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); + updateScreen(); + finishSound(); pause(14); - sentido_hare = 3; + trackProtagonist = 3; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); talk_solo(_textd[_lang][18], "d18.als"); - FundeAlNegro(1); + fadeToBlack(1); } void DrasculaEngine::animation_15_5() { - talk_mus(_texte[_lang][4], "E4.als"); - talk_mus(_texte[_lang][5], "E5.als"); - talk_mus(_texte[_lang][6], "E6.als"); - talk(_text[_lang][291], "291.als"); - talk_mus(_texte[_lang][7], "E7.als"); + talk_mus(4); + talk_mus(5); + talk_mus(6); + talk(291); + talk_mus(7); } void DrasculaEngine::animation_16_5() { - talk_mus(_texte[_lang][8], "E8.als"); + talk_mus(8); } void DrasculaEngine::animation_17_5() { - talk_mus(_texte[_lang][9], "E9.als"); + talk_mus(9); } void DrasculaEngine::animation_1_6() { - int l; - - sentido_hare = 0; - hare_x = 103; - hare_y = 108; + trackProtagonist = 0; + curX = 103; + curY = 108; flags[0] = 1; - for (l = 0; l < 200; l++) + for (int l = 0; l < 200; l++) factor_red[l] = 98; - loadPic("auxig2.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("auxdr.alg"); - decompressPic(dir_dibujo2, 1); - loadPic("car.alg"); - decompressPic(dir_hare_fondo, 1); - talk_dr_dch(_textd[_lang][19], "D19.als"); - talk(_text[_lang][247], "247.als"); - talk_dr_dch(_textd[_lang][20], "d20.als"); - talk_dr_dch(_textd[_lang][21], "d21.als"); - talk(_text[_lang][248], "248.als"); - talk_dr_dch(_textd[_lang][22], "d22.als"); - talk(_text[_lang][249], "249.als"); - talk_dr_dch(_textd[_lang][23], "d23.als"); - conversa("op_11.cal"); - talk_dr_dch(_textd[_lang][26], "d26.als"); - - anima("fum.bin", 15); - - talk_dr_dch(_textd[_lang][27], "d27.als"); - talk(_text[_lang][254], "254.als"); - talk_dr_dch(_textd[_lang][28], "d28.als"); - talk(_text[_lang][255], "255.als"); - talk_dr_dch(_textd[_lang][29], "d29.als"); - FundeAlNegro(1); + loadPic("auxig2.alg", frontSurface); + loadPic("auxdr.alg", drawSurface2); + loadPic("car.alg", backSurface); + talk_drascula(19, 1); + talk(247); + talk_drascula(20, 1); + talk_drascula(21, 1); + talk(248); + talk_drascula(22, 1); + talk(249); + talk_drascula(23, 1); + converse(11); + talk_drascula(26, 1); + + animate("fum.bin", 15); + + talk_drascula(27, 1); + talk(254); + talk_drascula(28, 1); + talk(255); + talk_drascula(29, 1); + fadeToBlack(1); clearRoom(); - loadPic("time1.alg"); - decompressPic(dir_zona_pantalla, 1); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("time1.alg", screenSurface); + updateScreen(); delay(930); clearRoom(); - Negro(); + black(); hare_se_ve = 0; flags[0] = 0; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - FundeDelNegro(1); - talk(_text[_lang][256], "256.als"); - talk_dr_dch(_textd[_lang][30], "d30.als"); - talk(_text[_lang][257], "257.als"); - FundeAlNegro(0); + updateScreen(); + fadeFromBlack(1); + talk(256); + talk_drascula(30, 1); + talk(257); + fadeToBlack(0); clearRoom(); - loadPic("time1.alg"); - decompressPic(dir_zona_pantalla,1); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("time1.alg", screenSurface); + updateScreen(); delay(900); clearRoom(); - Negro(); + black(); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - FundeDelNegro(1); - talk(_text[_lang][258], "258.als"); - talk_dr_dch(_textd[_lang][31], "d31.als"); + updateScreen(); + fadeFromBlack(1); + talk(258); + talk_drascula(31, 1); animation_5_6(); - talk_dr_dch(_textd[_lang][32], "d32.als"); - talk_igor_dch(_texti[_lang][11], "I11.als"); - sentido_igor = 3; - talk_dr_dch(_textd[_lang][33], "d33.als"); - talk_igor_frente(_texti[_lang][12], "I12.als"); - talk_dr_dch(_textd[_lang][34], "d34.als"); - sentido_dr = 0; - talk_dr_izq(_textd[_lang][35], "d35.als"); + talk_drascula(32, 1); + talk_igor(11, kIgorDch); + trackIgor = 3; + talk_drascula(33, 1); + talk_igor(12, kIgorFront); + talk_drascula(34, 1); + trackDrascula = 0; + talk_drascula(35); + + if (_lang == kSpanish) + textSurface = extraSurface; + clearRoom(); - carga_escoba("102.ald"); - activa_pendulo(); + enterRoom(102); + activatePendulum(); } void DrasculaEngine::animation_2_6() { - talk_dr_dch(_textd[_lang][24], "d24.als"); + talk_drascula(24, 1); } void DrasculaEngine::animation_3_6() { - talk_dr_dch(_textd[_lang][24], "d24.als"); + talk_drascula(24, 1); } void DrasculaEngine::animation_4_6() { - talk_dr_dch(_textd[_lang][25], "d25.als"); + talk_drascula(25, 1); } void DrasculaEngine::animation_5_6() { - int n, pos_pen[6]; - - pos_pen[0] = 1; - pos_pen[1] = 29; - pos_pen[2] = 204; - pos_pen[3] = -125; - pos_pen[4] = 18; - pos_pen[5] = 125; + int pos_pen[6] = { 1, 29, 204, -125, 18, 125 }; - anima("man.bin", 14); + animate("man.bin", 14); - for (n = -125; n <= 0; n = n + 2) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + for (int n = -125; n <= 0; n = n + 2) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); pos_pen[3] = n; - copyRectClip(pos_pen, dir_dibujo3, dir_zona_pantalla); + copyRectClip(pos_pen, drawSurface3, screenSurface); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(2); } @@ -2320,28 +1946,24 @@ void DrasculaEngine::animation_5_6() { } void DrasculaEngine::animation_6_6() { - anima("rct.bin", 11); + animate("rct.bin", 11); clearRoom(); - sin_verbo(); - resta_objeto(20); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - rompo = 1; - obj_saliendo = 104; - hare_x = -1; - sin_verbo(); - carga_escoba("58.ald"); + withoutVerb(); + removeObject(20); + loadPic(96, frontSurface); + loadPic(97, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); + doBreak = 1; + objExit = 104; + curX = -1; + withoutVerb(); + enterRoom(58); hare_se_ve = 1; - sentido_hare = 1; - anima("hbp.bin", 14); + trackProtagonist = 1; + animate("hbp.bin", 14); - sentido_hare = 3; + trackProtagonist = 3; flags[0] = 1; flags[1] = 0; flags[2] = 1; @@ -2349,926 +1971,597 @@ void DrasculaEngine::animation_6_6() { void DrasculaEngine::animation_7_6() { flags[8] = 1; - actualiza_datos(); + updateVisible(); } void DrasculaEngine::animation_9_6() { int v_cd; - anima("fin.bin", 14); - playmusic(13); + animate("fin.bin", 14); + playMusic(13); flags[5] = 1; - anima("drf.bin", 16); - FundeAlNegro(0); + animate("drf.bin", 16); + fadeToBlack(0); clearRoom(); - hare_x = -1; - obj_saliendo = 108; - carga_escoba("59.ald"); - strcpy(num_room, "nada.alg"); - loadPic("nota2.alg"); - decompressPic(dir_dibujo1, MEDIA); - Negro(); - sentido_hare = 1; - hare_x -= 21; + curX = -1; + objExit = 108; + enterRoom(59); + // The room number was originally changed here to "nada.alg", + // which is a non-existant file. In reality, this was just a + // hack to set the room number to a non-existant one, so that + // room sprites do not appear again when the room is refreshed. + // We set the room number to -1 for the same purpose. + // Also check animation_2_1(), where the same hack was used + // by the original + roomNumber = -1; + loadPic("nota2.alg", bgSurface, HALF_PAL); + black(); + trackProtagonist = 1; + curX -= 21; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - FundeDelNegro(0); + updateScreen(); + fadeFromBlack(0); pause(96); - lleva_al_hare(116, 178); - sentido_hare = 2; + gotoObject(116, 178); + trackProtagonist = 2; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - playmusic(9); + updateScreen(); + playMusic(9); clearRoom(); - loadPic("nota.alg"); - decompressPic(dir_dibujo1, COMPLETA); - color_abc(BLANCO); + loadPic("nota.alg", bgSurface, COMPLETE_PAL); + color_abc(kColorWhite); talk_solo(_textbj[_lang][24], "bj24.als"); talk_solo(_textbj[_lang][25], "bj25.als"); talk_solo(_textbj[_lang][26], "bj26.als"); talk_solo(_textbj[_lang][27], "bj27.als"); talk_solo(_textbj[_lang][28], "bj28.als"); - sentido_hare = 3; + trackProtagonist = 3; clearRoom(); - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("nota2.alg"); - decompressPic(dir_dibujo1, MEDIA); - talk(_text[_lang][296], "296.als"); - talk(_text[_lang][297], "297.als"); - talk(_text[_lang][298], "298.als"); - sentido_hare = 1; - talk(_text[_lang][299], "299.als"); - talk(_text[_lang][300], "300.als"); + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic("nota2.alg", bgSurface, HALF_PAL); + talk(296); + talk(297); + talk(298); + trackProtagonist = 1; + talk(299); + talk(300); updateRoom(); - copyBackground(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - color_abc(VERDE_CLARO); - talk_solo("GOOOOOOOOOOOOOOOL", "s15.als"); - loadPic("nota2.alg"); - decompressPic(dir_dibujo1, 1); - sentido_hare = 0; + copyBackground(0, 0, 0, 0, 320, 200, screenSurface, bgSurface); + updateScreen(); + color_abc(kColorLightGreen); + talk_solo(_textmisc[_lang][2], "s15.als"); + loadPic("nota2.alg", bgSurface); + trackProtagonist = 0; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk(_text[_lang][301], "301.als"); + updateScreen(); + talk(301); v_cd = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16; - v_cd = v_cd + 4; - playmusic(17); - FundeAlNegro(1); + v_cd += 4; + playMusic(17); + fadeToBlack(1); clearRoom(); - fliplay("qpc.bin", 1); + playFLI("qpc.bin", 1); MusicFadeout(); - stopmusic(); + stopMusic(); clearRoom(); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, v_cd * 16); - playmusic(3); - fliplay("crd.bin", 1); - stopmusic(); + playMusic(3); + playFLI("crd.bin", 1); + stopMusic(); } void DrasculaEngine::animation_10_6() { - comienza_sound ("s14.als"); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + playSound(14); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - copyBackground(164, 85, 155, 48, 113, 114, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); - talk_taber2(_textt[_lang][23], "t23.als"); + copyBackground(164, 85, 155, 48, 113, 114, drawSurface3, screenSurface); + updateScreen(); + finishSound(); + talk_bartender(23, 1); flags[7] = 1; } void DrasculaEngine::animation_11_6() { - talk_taber2(_textt[_lang][10], "t10.als"); - talk(_text[_lang][268], "268.als"); - talk_taber2(_textt[_lang][11], "t11.als"); + talk_bartender(10, 1); + talk(268); + talk_bartender(11, 1); } void DrasculaEngine::animation_12_6() { - talk_taber2(_textt[_lang][12], "t12.als"); - talk(_text[_lang][270], "270.als"); - talk_taber2(_textt[_lang][13], "t13.als"); - talk_taber2(_textt[_lang][14], "t14.als"); + talk_bartender(12, 1); + talk(270); + talk_bartender(13, 1); + talk_bartender(14, 1); } void DrasculaEngine::animation_13_6() { - talk_taber2(_textt[_lang][15], "t15.als"); + talk_bartender(15, 1); } void DrasculaEngine::animation_14_6() { - talk_taber2(_textt[_lang][24], "t24.als"); - suma_objeto(21); + talk_bartender(24, 1); + addObject(21); flags[10] = 1; - rompo_y_salgo = 1; + breakOut = 1; } void DrasculaEngine::animation_15_6() { - talk_taber2(_textt[_lang][16], "t16.als"); + talk_bartender(16, 1); } void DrasculaEngine::animation_18_6() { flags[6] = 1; - sin_verbo(); - resta_objeto(21); - anima("beb.bin", 10); + withoutVerb(); + removeObject(21); + animate("beb.bin", 10); } void DrasculaEngine::animation_19_6() { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyBackground(140, 23, 161, 69, 35, 80, dir_dibujo3, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyBackground(140, 23, 161, 69, 35, 80, drawSurface3, screenSurface); updateRefresh_pre(); - pon_hare(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + moveCharacters(); + updateScreen(); pause(6); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - comienza_sound("s4.als"); + updateScreen(); + playSound(4); pause(6); - fin_sound(); + finishSound(); } void DrasculaEngine::animation_12_2() { - loadPic("an12.alg"); - decompressPic(dir_hare_dch, 1); + if (_lang == kSpanish) + textSurface = frontSurface; + + loadPic("an12.alg", extraSurface); - talk(_text[_lang][356], "356.als"); + talk(356); updateRefresh_pre(); - copyBackground(1, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); - updateScreen(228, 112, 228, 112, 47, 60, dir_zona_pantalla); + copyBackground(1, 139, 228, 112, 47, 60, extraSurface, screenSurface); + updateScreen(228, 112, 228, 112, 47, 60, screenSurface); pause(3); updateRefresh_pre(); - copyBackground(49, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); - pon_hare(); + copyBackground(49, 139, 228, 112, 47, 60, extraSurface, screenSurface); + moveCharacters(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(3); - stopmusic(); + stopMusic(); flags[11] = 1; - talk_pianista(_textp[_lang][5], "P5.als"); - conversa("op_1.cal"); + talk_pianist(5); + converse(1); + + if (_lang == kSpanish) + textSurface = extraSurface; flags[11] = 0; - loadPic("974.alg"); - decompressPic(dir_hare_dch, 1); + loadPic(974, extraSurface); } void DrasculaEngine::animation_26_2() { - int n, x = 0; + if (_lang == kSpanish) + textSurface = frontSurface; - loadPic("an12.alg"); - decompressPic(dir_hare_dch, 1); + loadPic("an12.alg", extraSurface); - talk(_text[_lang][392], "392.als"); + talk(392); updateRefresh_pre(); - copyBackground(1, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); - updateScreen(228, 112, 228, 112, 47, 60, dir_zona_pantalla); + copyBackground(1, 139, 228, 112, 47, 60, extraSurface, screenSurface); + updateScreen(228, 112, 228, 112, 47, 60, screenSurface); pause(3); updateRefresh_pre(); - copyBackground(49, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); - pon_hare(); + copyBackground(49, 139, 228, 112, 47, 60, extraSurface, screenSurface); + moveCharacters(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(3); - stopmusic(); + stopMusic(); flags[11] = 1; - talk_pianista(_textp[_lang][5], "P5.als"); - talk(_text[_lang][393], "393.als"); - talk_pianista(_textp[_lang][17], "P17.als"); - talk_pianista(_textp[_lang][18], "P18.als"); - talk_pianista(_textp[_lang][19], "P19.als"); + talk_pianist(5); + talk(393); + talk_pianist(17); + talk_pianist(18); + talk_pianist(19); - loadPic("an26.alg"); - decompressPic(dir_hare_dch, 1); - for (n = 0; n < 6; n++){ - x++; - copyBackground(x, 1, 225, 113, 50, 59, dir_hare_dch, dir_zona_pantalla); - updateScreen(225,113, 225,113, 50,59, dir_zona_pantalla); - x = x + 50; - pause(3); - } + loadPic("an26.alg", extraSurface); + + updateAnim(1, 225, 113, 50, 59, 6, extraSurface); - x = 0; - for (n = 0; n < 6; n++) { + int x = 0; + for (int n = 0; n < 6; n++) { x++; - copyBackground(x, 61, 225, 113, 50, 59, dir_hare_dch, dir_zona_pantalla); - updateScreen(225, 113, 225, 113, 50, 59, dir_zona_pantalla); + copyBackground(x, 61, 225, 113, 50, 59, extraSurface, screenSurface); + updateScreen(225, 113, 225, 113, 50, 59, screenSurface); x = x + 50; if (n == 2) - comienza_sound("s9.als"); + playSound(9); pause(3); } - fin_sound_corte(); - x = 0; - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 121, 225, 113, 50, 59, dir_hare_dch, dir_zona_pantalla); - updateScreen(225, 113, 225, 113, 50, 59, dir_zona_pantalla); - x = x + 50; - pause(3); - } + stopSound(); + + updateAnim(121, 225, 113, 50, 59, 6, extraSurface); + + pickObject(11); + removeObject(kItemBook); - agarra_objeto(11); - resta_objeto(12); + if (_lang == kSpanish) + textSurface = extraSurface; flags[11] = 0; flags[39] = 1; - loadPic("974.alg"); - decompressPic(dir_hare_dch, 1); - musica_room = 16; + loadPic(974, extraSurface); + roomMusic = 16; } void DrasculaEngine::animation_11_2() { - loadPic("an11y13.alg"); - decompressPic(dir_hare_dch, 1); - - talk(_text[_lang][352], "352.als"); - talk_tabernero(_textt[_lang][1], "T1.als"); - talk(_text[_lang][353], "353.als"); - talk_tabernero(_textt[_lang][17], "T17.als"); - talk(_text[_lang][354], "354.als"); - talk_tabernero(_textt[_lang][18], "T18.als"); - talk(_text[_lang][355], "355.als"); + if (_lang == kSpanish) + textSurface = frontSurface; + + loadPic("an11y13.alg", extraSurface); + + talk(352); + talk_bartender(1); + talk(353); + talk_bartender(17); + talk(354); + talk_bartender(18); + talk(355); pause(40); - talk_tabernero("No, nada", "d82.als"); + talk_bartender(82); - loadPic("974.alg"); - decompressPic(dir_hare_dch, 1); + if (_lang == kSpanish) + textSurface = extraSurface; + + loadPic(974, extraSurface); } void DrasculaEngine::animation_13_2() { - loadPic("an11y13.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an11y13.alg", frontSurface); if (flags[41] == 0) { - talk(_text[_lang][103], "103.als"); - talk_borracho(_textb[_lang][4], "B4.als"); + talk(103); + talk_drunk(4); flags[12] = 1; - talk(_text[_lang][367], "367.als"); - talk_borracho(_textb[_lang][5], "B5.als"); + talk(367); + talk_drunk(5); flags[12] = 1; - talk(_text[_lang][368], "368.als"); - talk_borracho(_textb[_lang][6], "B6.als"); - talk_borracho(_textb[_lang][7], "B7.als"); + talk(368); + talk_drunk(6); + talk_drunk(7); flags[41] = 1; } - conversa("op_2.cal"); + converse(2); - loadPic("964.alg"); - decompressPic(dir_hare_frente, 1); + loadPic(964, frontSurface); } void DrasculaEngine::animation_18_2() { - talk(_text[_lang][378], "378.als"); - talk_vbpuerta(_textvb[_lang][4], "VB4.als"); - conversa("op_3.cal"); + talk(378); + talk_vonBraunpuerta(4); + converse(3); } void DrasculaEngine::animation_22_2() { - talk(_text[_lang][374],"374.als"); + talk(374); - sentido_hare=2; + trackProtagonist=2; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - comienza_sound("s13.als"); - fin_sound(); - sentido_hare = 1; + updateScreen(); + playSound(13); + finishSound(); + trackProtagonist = 1; - talk_vbpuerta(_textvb[_lang][1], "VB1.als"); - talk(_text[_lang][375], "375.als"); - talk_vbpuerta(_textvb[_lang][2], "VB2.als"); - talk(_text[_lang][376], "376.als"); - talk_vbpuerta(_textvb[_lang][3], "VB3.als"); + talk_vonBraunpuerta(1); + talk(375); + talk_vonBraunpuerta(2); + talk(376); + talk_vonBraunpuerta(3); flags[18] = 1; } void DrasculaEngine::animation_24_2() { - if (hare_x < 178) - lleva_al_hare(208, 136); - sentido_hare = 3; + if (curX < 178) + gotoObject(208, 136); + trackProtagonist = 3; updateRoom(); pause(3); - sentido_hare = 0; + trackProtagonist = 0; - talk(_text[_lang][356], "356.als"); + talk(356); - loadPic("an24.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an24.alg", frontSurface); animation_32_2(); flags[21] = 1; - talk_vb(_textvb[_lang][22], "VB22.als"); + talk_vonBraun(22); if (flags[22] == 0) - conversa("op_4.cal"); + converse(4); else - conversa("op_5.cal"); + converse(5); - sal_de_la_habitacion(0); + exitRoom(0); flags[21] = 0; flags[24] = 0; - sentido_vb = 1; - vb_x = 120; + trackVonBraun = 1; + vonBraunX = 120; } void DrasculaEngine::animation_32_2() { - int n, x = 0; - - loadPic("an32_1.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("an32_2.alg"); - decompressPic(dir_hare_fondo, 1); - - for (n = 0; n < 4; n++) { - x++; - copyBackground(x, 1, 113, 53, 65, 81, dir_dibujo3, dir_zona_pantalla); - updateScreen(113, 53, 113, 53, 65, 81, dir_zona_pantalla); - x = x + 65; - pause(4); - } - - x = 0; - for (n = 0; n < 4; n++) { - x++; - copyBackground(x, 83, 113, 53, 65, 81, dir_dibujo3, dir_zona_pantalla); - updateScreen(113, 53, 113, 53, 65, 81, dir_zona_pantalla); - x = x + 65; - pause(4); - } + loadPic("an32_1.alg", drawSurface3); + loadPic("an32_2.alg", backSurface); - x = 0; - for (n = 0; n < 4; n++) { - x++; - copyBackground(x, 1, 113, 53, 65, 81, dir_hare_fondo, dir_zona_pantalla); - updateScreen(113, 53, 113, 53, 65, 81, dir_zona_pantalla); - x = x + 65; - pause(4); - } + updateAnim(1, 113, 53, 65, 81, 4, drawSurface3, 4); + updateAnim(83, 113, 53, 65, 81, 4, drawSurface3, 4); + updateAnim(1, 113, 53, 65, 81, 4, backSurface, 4); - x = 0; - for (n = 0; n < 3; n++) { + int x = 0; + for (int n = 0; n < 3; n++) { x++; - copyBackground(x, 83, 113, 53, 65, 81, dir_hare_fondo, dir_zona_pantalla); - updateScreen(113, 53, 113, 53, 65, 81, dir_zona_pantalla); + copyBackground(x, 83, 113, 53, 65, 81, backSurface, screenSurface); + updateScreen(113, 53, 113, 53, 65, 81, screenSurface); x = x + 65; if (n < 2) pause(4); } - loadPic("aux18.alg"); - decompressPic(dir_dibujo3, 1); + loadPic("aux18.alg", drawSurface3); } void DrasculaEngine::animation_34_2() { - int n, x = 0; - - sentido_hare = 1; + trackProtagonist = 1; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - loadPic("an34_1.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an34_2.alg"); - decompressPic(dir_hare_dch, 1); + loadPic("an34_1.alg", backSurface); + loadPic("an34_2.alg", extraSurface); - for (n = 0; n < 3; n++) { - x++; - copyBackground(x, 1, 218, 79, 83, 75, dir_hare_fondo, dir_zona_pantalla); - updateScreen(218, 79, 218, 79, 83, 75, dir_zona_pantalla); - x = x + 83; - pause(3); - } - - x = 0; + updateAnim(1, 218, 79, 83, 75, 3, backSurface); + updateAnim(77, 218, 79, 83, 75, 3, backSurface); - for (n = 0; n < 3; n++) { - x++; - copyBackground(x, 77, 218, 79, 83, 75, dir_hare_fondo, dir_zona_pantalla); - updateScreen(218, 79, 218, 79, 83, 75, dir_zona_pantalla); - x = x + 83; - pause(3); - } + playSound(8); - x = 0; - comienza_sound("s8.als"); + updateAnim(1, 218, 79, 83, 75, 3, extraSurface); - for (n = 0; n < 3; n++) { - x++; - copyBackground(x, 1, 218, 79, 83, 75, dir_hare_dch, dir_zona_pantalla); - updateScreen(218, 79, 218, 79, 83,75, dir_zona_pantalla); - x = x + 83; - pause(3); - } - fin_sound(); + finishSound(); pause(30); - copyBackground(1, 77, 218, 79, 83, 75, dir_hare_dch, dir_zona_pantalla); - updateScreen(218, 79, 218, 79, 83, 75, dir_zona_pantalla); + copyBackground(1, 77, 218, 79, 83, 75, extraSurface, screenSurface); + updateScreen(218, 79, 218, 79, 83, 75, screenSurface); pause(3); - loadPic("994.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("974.alg"); - decompressPic(dir_hare_dch, 1); + loadPic(994, backSurface); + loadPic(974, extraSurface); } void DrasculaEngine::animation_36_2() { - loadPic("an11y13.alg"); - decompressPic(dir_hare_dch, 1); - - talk(_text[_lang][404], "404.als"); - talk_tabernero(_textt[_lang][19], "T19.als"); - talk_tabernero(_textt[_lang][20], "T20.als"); - talk_tabernero(_textt[_lang][21], "T21.als"); - talk(_text[_lang][355], "355.als"); + if (_lang == kSpanish) + textSurface = frontSurface; + + loadPic("an11y13.alg", extraSurface); + + talk(404); + talk_bartender(19); + talk_bartender(20); + talk_bartender(21); + talk(355); pause(40); - talk_tabernero("No, nada", "d82.als"); + talk_bartender(82); + + if (_lang == kSpanish) + textSurface = extraSurface; - loadPic("974.alg"); - decompressPic(dir_hare_dch, 1); + loadPic(974, extraSurface); } void DrasculaEngine::animation_7_2() { - int n, x = 0; - - loadPic("an7_1.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an7_2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("an7_3.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an7_1.alg", backSurface); + loadPic("an7_2.alg", extraSurface); + loadPic("an7_3.alg", frontSurface); if (flags[3] == 1) - copyBackground(258, 110, 85, 44, 23, 53, dir_dibujo3, dir_dibujo1); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_fondo, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_fondo, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_frente, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - loadPic("an7_4.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an7_5.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("an7_6.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("an7_7.alg"); - decompressPic(dir_dibujo3, 1); - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_fondo, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_fondo, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; + copyBackground(258, 110, 85, 44, 23, 53, drawSurface3, bgSurface); - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51,73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - x = 0; + updateScreen(); - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } + updateAnim2(1, 80, 64, 51, 73, 6, backSurface); + updateAnim2(75, 80, 64, 51, 73, 6, backSurface); + updateAnim2(1, 80, 64, 51, 73, 6, extraSurface); + updateAnim2(75, 80, 64, 51, 73, 6, extraSurface); + updateAnim2(1, 80, 64, 51, 73, 6, frontSurface); - x = 0; + loadPic("an7_4.alg", backSurface); + loadPic("an7_5.alg", extraSurface); + loadPic("an7_6.alg", frontSurface); + loadPic("an7_7.alg", drawSurface3); - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_frente, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } + updateAnim2(1, 80, 64, 51, 73, 6, backSurface); + updateAnim2(75, 80, 64, 51, 73, 6, backSurface); + updateAnim2(1, 80, 64, 51, 73, 6, extraSurface); + updateAnim2(75, 80, 64, 51, 73, 6, extraSurface); + updateAnim2(1, 80, 64, 51, 73, 6, frontSurface); + updateAnim2(75, 80, 64, 51, 73, 6, extraSurface); + updateAnim2(1, 80, 64, 51, 73, 6, frontSurface); + updateAnim2(75, 80, 64, 51, 73, 6, frontSurface); + updateAnim2(1, 80, 64, 51, 73, 6, drawSurface3); + updateAnim2(75, 80, 64, 51, 73, 2, drawSurface3); - x = 0; + loadPic("an7_8.alg", backSurface); + loadPic("an7_9.alg", extraSurface); - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } + updateAnim2(1, 80, 64, 51, 73, 6, backSurface); + updateAnim2(75, 80, 64, 51, 73, 6, backSurface); + updateAnim2(1, 80, 64, 51, 73, 6, extraSurface); - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_frente, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_frente, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_dibujo3, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 2; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_dibujo3, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - loadPic("an7_8.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an7_9.alg"); - decompressPic(dir_hare_dch, 1); - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_fondo, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 75, 80, 64, 51, 73, dir_hare_fondo, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(x, 1, 80, 64, 51, 73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); - x = x + 51; - pause(3); - } - - - copyBackground(80, 64, 80, 64, 51, 73, dir_dibujo1, dir_zona_pantalla); - copyRect(1, 75, 80, 64, 51, 73, dir_hare_dch, dir_zona_pantalla); - updateScreen(80, 64, 80, 64, 51, 73, dir_zona_pantalla); + copyBackground(80, 64, 80, 64, 51, 73, bgSurface, screenSurface); + copyRect(1, 75, 80, 64, 51, 73, extraSurface, screenSurface); + updateScreen(80, 64, 80, 64, 51, 73, screenSurface); flags[37] = 1; if (flags[7] == 1 && flags[26] == 1 && flags[34] == 1 && flags[35] == 1 && flags[37] == 1) flags[38] = 1; - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("aux3.alg"); - decompressPic(dir_dibujo3, 1); + loadPic(99, backSurface); + loadPic(97, extraSurface); + loadPic(96, frontSurface); + loadPic("aux3.alg", drawSurface3); } void DrasculaEngine::animation_5_2() { - int n, x = 0; - - sentido_hare = 0; + trackProtagonist = 0; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - loadPic("an5_1.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("an5_2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("an5_3.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("an5_4.alg"); - decompressPic(dir_dibujo3, 1); + loadPic("an5_1.alg", backSurface); + loadPic("an5_2.alg", extraSurface); + loadPic("an5_3.alg", frontSurface); + loadPic("an5_4.alg", drawSurface3); - copyBackground(1, 1, 213, 66, 53,84, dir_hare_fondo, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyBackground(1, 1, 213, 66, 53,84, backSurface, screenSurface); + updateScreen(); - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 213, 66, 53, 84, dir_hare_fondo, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84,dir_zona_pantalla); - x = x + 52; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 86, 213, 66, 53, 84, dir_hare_fondo, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 213, 66, 53, 84, dir_hare_dch, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 213, 66, 53, 84, dir_hare_dch, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 86, 213, 66, 53, 84, dir_hare_dch, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } - - x = 0; + updateAnim(1, 213, 66, 52, 84, 6, backSurface); + updateAnim(86, 213, 66, 52, 84, 6, backSurface); + updateAnim(1, 213, 66, 52, 84, 6, extraSurface); + updateAnim(1, 213, 66, 52, 84, 6, extraSurface); + updateAnim(86, 213, 66, 52, 84, 6, extraSurface); + updateAnim(1, 213, 66, 52, 84, 6, frontSurface); - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 213, 66, 53, 84, dir_hare_frente, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } - - comienza_sound("s1.als"); - - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 86, 213, 66, 53, 84, dir_hare_frente, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } - fin_sound_corte(); + playSound(1); + updateAnim(86, 213, 66, 52, 84, 6, frontSurface); + stopSound(); - x = 0; - - for (n = 0; n < 6; n++) { - x++; - copyBackground(x, 1, 213, 66, 53, 84, dir_dibujo3, dir_zona_pantalla); - updateScreen(213, 66, 213, 66, 53, 84, dir_zona_pantalla); - x = x + 52; - pause(3); - } + updateAnim(1, 213, 66, 52, 84, 6, drawSurface3); - loadPic("994.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("974.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("964.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("aux5.alg"); - decompressPic(dir_dibujo3, 1); + loadPic(994, backSurface); + loadPic(974, extraSurface); + loadPic(964, frontSurface); + loadPic("aux5.alg", drawSurface3); flags[8] = 1; - hare_x = hare_x - 4; - talk_sinc(_text[_lang][46], "46.als", "4442444244244"); - sin_verbo(); + curX = curX - 4; + talk_sync(_text[_lang][46], "46.als", "4442444244244"); + withoutVerb(); } void DrasculaEngine::animation_6_2() { - stopmusic(); + stopMusic(); flags[9] = 1; + if (_lang == kSpanish) + textSurface = frontSurface; + clearRoom(); - loadPic("ciego1.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("ciego2.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("ciego3.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("ciego4.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("ciego5.alg"); - decompressPic(dir_hare_frente, 1); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("ciego1.alg", bgSurface, HALF_PAL); // ciego = blind + loadPic("ciego2.alg", drawSurface3); + loadPic("ciego3.alg", extraSurface); + loadPic("ciego4.alg", backSurface); + loadPic("ciego5.alg", frontSurface); + + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); pause(1); if (flags[4] == 1) - talk_hacker(_textd[_lang][66], "d66.als"); + talk_hacker(66); pause(6); - talk_ciego(_textd[_lang][78], "d78.als", - "004447222550002222755554444466222000220555002220550444446666662220000557550033344477222522665444466663337446055504446550550550222633003330000666622044422755722270255566667555655007222777"); + talk_blind(11); pause(4); - talk_hacker(_textd[_lang][67], "d67.als"); + talk_hacker(67); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); pause(10); clearRoom(); - playmusic(musica_room); - loadPic("9.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("aux9.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - sin_verbo(); + playMusic(roomMusic); + loadPic(9, bgSurface, HALF_PAL); + loadPic("aux9.alg", drawSurface3); + loadPic(96, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); + withoutVerb(); + + if (_lang == kSpanish) + textSurface = extraSurface; flags[9] = 0; } void DrasculaEngine::animation_33_2() { - stopmusic(); + stopMusic(); flags[9] = 1; pause(12); - talk(_textd[_lang][56], "d56.als" ); + talk(56); pause(8); clearRoom(); - loadPic("ciego1.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("ciego2.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("ciego3.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("ciego4.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("ciego5.alg"); - decompressPic(dir_hare_frente, 1); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + loadPic("ciego1.alg", bgSurface, HALF_PAL); // ciego = blind + loadPic("ciego2.alg", drawSurface3); + loadPic("ciego3.alg", extraSurface); + loadPic("ciego4.alg", backSurface); + loadPic("ciego5.alg", frontSurface); + + if (_lang == kSpanish) + textSurface = frontSurface; + + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); pause(10); - talk_ciego(_textd[_lang][68], "d68.als", "44472225500022227555544444472225500022227555544444664466"); + talk_blind(1); pause(5); - talk_hacker(_textd[_lang][57], "d57.als"); + talk_hacker(57); pause(6); _system->delayMillis(1000); - talk_ciego(_textd[_lang][77], "d77.als", "56665004444447222550002222755554444466555033022755555000444444444444444444444444444444"); - talk_hacker(_textd[_lang][65], "d65.als"); + talk_blind(10); + talk_hacker(65); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); pause(14); clearRoom(); - playmusic(musica_room); - loadPic("9.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("aux9.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - sin_verbo(); + playMusic(roomMusic); + loadPic(9, bgSurface, HALF_PAL); + loadPic("aux9.alg", drawSurface3); + loadPic(96, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); + withoutVerb(); + + if (_lang == kSpanish) + textSurface = extraSurface; flags[33] = 1; flags[9] = 0; @@ -3276,147 +2569,146 @@ void DrasculaEngine::animation_33_2() { void DrasculaEngine::animation_1_4() { if (flags[21] == 0) { - strcpy(nombre_obj[2], "igor"); - talk(_text[_lang][275], "275.als"); + strcpy(objName[2], "igor"); + talk(275); updateRefresh_pre(); - copyBackground(131, 133, 199, 95, 50, 66, dir_dibujo3, dir_zona_pantalla); - updateScreen(199, 95, 199, 95, 50, 66, dir_zona_pantalla); + copyBackground(131, 133, 199, 95, 50, 66, drawSurface3, screenSurface); + updateScreen(199, 95, 199, 95, 50, 66, screenSurface); pause(3); updateRefresh_pre(); - copyBackground(182, 133, 199, 95, 50, 66, dir_dibujo3, dir_zona_pantalla); - pon_hare(); + copyBackground(182, 133, 199, 95, 50, 66, drawSurface3, screenSurface); + moveCharacters(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(3); flags[18] = 1; flags[20] = 1; - talk_igor_sentado(_texti[_lang][13], "I13.als"); - talk_igor_sentado(_texti[_lang][14], "I14.als"); - talk_igor_sentado(_texti[_lang][15], "I15.als"); + talk_igor(13, kIgorSeated); + talk_igor(14, kIgorSeated); + talk_igor(15, kIgorSeated); flags[21] = 1; } else { - talk(_text[_lang][356], "356.als"); + talk(356); updateRefresh_pre(); - copyBackground(131, 133, 199, 95, 50, 66, dir_dibujo3, dir_zona_pantalla); - updateScreen(199, 95, 199, 95, 50, 66, dir_zona_pantalla); + copyBackground(131, 133, 199, 95, 50, 66, drawSurface3, screenSurface); + updateScreen(199, 95, 199, 95, 50, 66, screenSurface); pause(2); updateRefresh_pre(); - copyBackground(182, 133, 199, 95, 50, 66, dir_dibujo3, dir_zona_pantalla); - pon_hare(); + copyBackground(182, 133, 199, 95, 50, 66, drawSurface3, screenSurface); + moveCharacters(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); flags[18] = 1; flags[20] = 1; - talk(_text[_lang][276], "276.als"); + talk(276); pause(14); - talk_igor_sentado(_texti[_lang][6], "I6.als"); + talk_igor(6, kIgorSeated); } - conversa("op_6.cal"); + converse(6); flags[20] = 0; flags[18] = 0; } void DrasculaEngine::animation_5_4(){ - sentido_hare = 3; - loadPic("anh_dr.alg"); - decompressPic(dir_hare_fondo, 1); - lleva_al_hare(99, 160); - lleva_al_hare(38, 177); + trackProtagonist = 3; + loadPic("anh_dr.alg", backSurface); + gotoObject(99, 160); + gotoObject(38, 177); hare_se_ve = 0; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); delay(800); - anima("bio.bin", 14); + animate("bio.bin", 14); flags[29] = 1; - hare_x = 95; - hare_y = 82; + curX = 95; + curY = 82; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - abre_puerta(2, 0); - loadPic("auxigor.alg"); - decompressPic(dir_hare_frente, 1); - x_igor = 100; - y_igor = 65; - talk_igor_frente(_texti[_lang][29], "I29.ALS"); - talk_igor_frente(_texti[_lang][30], "I30.als"); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); + updateScreen(); + openDoor(2, 0); + loadPic("auxigor.alg", frontSurface); + igorX = 100; + igorY = 65; + talk_igor(29, kIgorFront); + talk_igor(30, kIgorFront); + loadPic(96, frontSurface); + loadPic(99, backSurface); hare_se_ve = 1; - FundeAlNegro(0); - sal_de_la_habitacion(0); + fadeToBlack(0); + exitRoom(0); } void DrasculaEngine::animation_6_4() { - char room[13]; + int prevRoom = roomNumber; - strcpy(room, num_room); - strcpy(num_room, "26.alg"); + roomNumber = 26; clearRoom(); - loadPic("26.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("aux26.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("auxigor.alg"); - decompressPic(dir_hare_frente, 1); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + loadPic(26, bgSurface, HALF_PAL); + loadPic("aux26.alg", drawSurface3); + loadPic("auxigor.alg", frontSurface); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); update_26_pre(); - x_igor = 104; - y_igor = 71; - pon_igor(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + igorX = 104; + igorY = 71; + placeIgor(); + updateScreen(); pause(40); - talk_igor_frente(_texti[_lang][26], "I26.als"); - strcpy(num_room, room); + talk_igor(26, kIgorFront); + roomNumber = prevRoom; clearRoom(); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic(roomDisk); - decompressPic(dir_dibujo3, 1); - loadPic(num_room); - decompressPic(dir_dibujo1, MEDIA); - sin_verbo(); + loadPic(96, frontSurface); + loadPic(roomDisk, drawSurface3); + loadPic(roomNumber, bgSurface, HALF_PAL); + withoutVerb(); updateRoom(); } void DrasculaEngine::animation_8_4() { - int frame; - int estanteria_x[] = {1, 75, 149, 223, 1, 75, 149, 223, 149, 223, 149, 223, 149, 223}; - int estanteria_y[] = {1, 1, 1, 1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74}; + int bookcaseX[] = {1, 75, 149, 223, 1, 75, 149, 223, 149, 223, 149, 223, 149, 223}; + int bookcaseY[] = {1, 1, 1, 1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74}; - loadPic("an_8.alg"); - decompressPic(dir_hare_frente, 1); + loadPic("an_8.alg", frontSurface); - for (frame = 0; frame < 14; frame++) { + for (int frame = 0; frame < 14; frame++) { pause(2); - copyBackground(estanteria_x[frame], estanteria_y[frame], 77, 45, 73, 72, dir_hare_frente, dir_zona_pantalla); - updateScreen(77, 45, 77, 45, 73, 72, dir_zona_pantalla); + copyBackground(bookcaseX[frame], bookcaseY[frame], 77, 45, 73, 72, frontSurface, screenSurface); + updateScreen(77, 45, 77, 45, 73, 72, screenSurface); } - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - abre_puerta(7, 2); + loadPic(96, frontSurface); + openDoor(7, 2); } void DrasculaEngine::animation_9_4() { - anima("st.bin", 14); - FundeAlNegro(1); + animate("st.bin", 14); + fadeToBlack(1); } +void DrasculaEngine::activatePendulum() { + flags[1] = 2; + hare_se_ve = 0; + roomNumber = 102; + loadPic(102, bgSurface, HALF_PAL); + loadPic("an_p1.alg", drawSurface3); + loadPic("an_p2.alg", extraSurface); + loadPic("an_p3.alg", frontSurface); + + copyBackground(0, 171, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3); + + savedTime = getTime(); +} } // End of namespace Drascula diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp new file mode 100644 index 0000000000..1c3831e4ca --- /dev/null +++ b/engines/drascula/converse.cpp @@ -0,0 +1,297 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::converse(int index) { + char fileName[20]; + sprintf(fileName, "op_%d.cal", index); + uint h; + int game1 = 1, game2 = 1, game3 = 1, game4 = 1; + char phrase1[78]; + char phrase2[78]; + char phrase3[87]; + char phrase4[78]; + char sound1[13]; + char sound2[13]; + char sound3[13]; + char sound4[13]; + int answer1; + int answer2; + int answer3; + int used1 = 0; + int used2 = 0; + int used3 = 0; + char buffer[256]; + uint len; + + breakOut = 0; + + if (currentChapter == 5) + withoutVerb(); + + _arj.open(fileName); + if (!_arj.isOpen()) { + error("missing data file %s", fileName); + } + int size = _arj.size(); + + getStringFromLine(buffer, size, phrase1); + getStringFromLine(buffer, size, phrase2); + getStringFromLine(buffer, size, phrase3); + getStringFromLine(buffer, size, phrase4); + getStringFromLine(buffer, size, sound1); + getStringFromLine(buffer, size, sound2); + getStringFromLine(buffer, size, sound3); + getStringFromLine(buffer, size, sound4); + getIntFromLine(buffer, size, &answer1); + getIntFromLine(buffer, size, &answer2); + getIntFromLine(buffer, size, &answer3); + + _arj.close(); + + if (currentChapter == 2 && !strcmp(fileName, "op_5.cal") && flags[38] == 1 && flags[33] == 1) { + strcpy(phrase3, _text[_lang][405]); + strcpy(sound3, "405.als"); + answer3 = 31; + } + + if (currentChapter == 6 && !strcmp(fileName, "op_12.cal") && flags[7] == 1) { + strcpy(phrase3, _text[_lang][273]); + strcpy(sound3, "273.als"); + answer3 = 14; + } + + if (currentChapter == 6 && !strcmp(fileName, "op_12.cal") && flags[10] == 1) { + strcpy(phrase3, _text[_lang][274]); + strcpy(sound3, "274.als"); + answer3 = 15; + } + + len = strlen(phrase1); + for (h = 0; h < len; h++) + if (phrase1[h] == (char)0xa7) + phrase1[h] = ' '; + + len = strlen(phrase2); + for (h = 0; h < len; h++) + if (phrase2[h] == (char)0xa7) + phrase2[h] = ' '; + + len = strlen(phrase3); + for (h = 0; h < len; h++) + if (phrase3[h] == (char)0xa7) + phrase3[h] = ' '; + + len = strlen(phrase4); + for (h = 0; h < len; h++) + if (phrase4[h] == (char)0xa7) + phrase4[h] = ' '; + + loadPic("car.alg", backSurface); + // TODO code here should limit y position for mouse in dialog menu, + // but we can't implement this due lack backend functionality + // from 1(top) to 31 + color_abc(kColorLightGreen); + + while (breakOut == 0) { + updateRoom(); + + if (currentChapter == 1 || currentChapter == 4 || currentChapter == 6) { + if (musicStatus() == 0 && flags[11] == 0) + playMusic(roomMusic); + } else if (currentChapter == 2) { + if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0) + playMusic(roomMusic); + } else if (currentChapter == 3 || currentChapter == 5) { + if (musicStatus() == 0) + playMusic(roomMusic); + } + + updateEvents(); + + if (mouseY > 0 && mouseY < 9) { + if (used1 == 1 && _color != kColorWhite) + color_abc(kColorWhite); + else if (used1 == 0 && _color != kColorLightGreen) + color_abc(kColorLightGreen); + } else if (mouseY > 8 && mouseY < 17) { + if (used2 == 1 && _color != kColorWhite) + color_abc(kColorWhite); + else if (used2 == 0 && _color != kColorLightGreen) + color_abc(kColorLightGreen); + } else if (mouseY > 16 && mouseY < 25) { + if (used3 == 1 && _color != kColorWhite) + color_abc(kColorWhite); + else if (used3 == 0 && _color != kColorLightGreen) + color_abc(kColorLightGreen); + } else if (_color != kColorLightGreen) + color_abc(kColorLightGreen); + + if (mouseY > 0 && mouseY < 9) + game1 = 2; + else if (mouseY > 8 && mouseY < 17) + game2 = 2; + else if (mouseY > 16 && mouseY < 25) + game3 = 2; + else if (mouseY > 24 && mouseY < 33) + game4 = 2; + + print_abc_opc(phrase1, 1, 2, game1); + print_abc_opc(phrase2, 1, 10, game2); + print_abc_opc(phrase3, 1, 18, game3); + print_abc_opc(phrase4, 1, 26, game4); + + updateScreen(); + + if ((leftMouseButton == 1) && (game1 == 2)) { + delay(100); + used1 = 1; + talk(phrase1, sound1); + if (currentChapter == 3) + grr(); + else + response(answer1); + } else if ((leftMouseButton == 1) && (game2 == 2)) { + delay(100); + used2 = 1; + talk(phrase2, sound2); + if (currentChapter == 3) + grr(); + else + response(answer2); + } else if ((leftMouseButton == 1) && (game3 == 2)) { + delay(100); + used3 = 1; + talk(phrase3, sound3); + if (currentChapter == 3) + grr(); + else + response(answer3); + } else if ((leftMouseButton == 1) && (game4 == 2)) { + delay(100); + talk(phrase4, sound4); + breakOut = 1; + } + + if (leftMouseButton == 1) { + delay(100); + color_abc(kColorLightGreen); + } + + game1 = (used1 == 0) ? 1 : 3; + game2 = (used2 == 0) ? 1 : 3; + game3 = (used3 == 0) ? 1 : 3; + game4 = 1; + } // while (breakOut == 0) + + if (currentChapter == 2) + loadPic(menuBackground, backSurface); + else + loadPic(99, backSurface); + if (currentChapter != 5) + withoutVerb(); +} + +void DrasculaEngine::response(int function) { + if (currentChapter == 1) { + if (function >= 10 && function <= 12) + talk_drunk(function - 9); + } else if (currentChapter == 2) { + if (function == 8) + animation_8_2(); + else if (function == 9) + animation_9_2(); + else if (function == 10) + animation_10_2(); + else if (function == 15) + animation_15_2(); + else if (function == 16) + animation_16_2(); + else if (function == 17) + animation_17_2(); + else if (function == 19) + animation_19_2(); + else if (function == 20) + animation_20_2(); + else if (function == 21) + animation_21_2(); + else if (function == 23) + animation_23_2(); + else if (function == 28) + animation_28_2(); + else if (function == 29) + animation_29_2(); + else if (function == 30) + animation_30_2(); + else if (function == 31) + animation_31_2(); + } else if (currentChapter == 4) { + if (function == 2) + animation_2_4(); + else if (function == 3) + animation_3_4(); + else if (function == 4) + animation_4_4(); + } else if (currentChapter == 5) { + if (function == 2) + animation_2_5(); + else if (function == 3) + animation_3_5(); + else if (function == 6) + animation_6_5(); + else if (function == 7) + animation_7_5(); + else if (function == 8) + animation_8_5(); + else if (function == 15) + animation_15_5(); + else if (function == 16) + animation_16_5(); + else if (function == 17) + animation_17_5(); + } else if (currentChapter == 6) { + if (function == 2) + animation_2_6(); + else if (function == 3) + animation_3_6(); + else if (function == 4) + animation_4_6(); + else if (function == 11) + animation_11_6(); + else if (function == 12) + animation_12_6(); + else if (function == 13) + animation_13_6(); + else if (function == 14) + animation_14_6(); + else if (function == 15) + animation_15_6(); + } +} + +} // End of namespace Drascula diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 80ea4f0eab..a426857fbd 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -35,27 +35,25 @@ namespace Drascula { struct DrasculaGameDescription { Common::ADGameDescription desc; - - int gameID; - int gameType; - uint32 features; - uint16 version; }; -uint32 DrasculaEngine::getGameID() const { - return _gameDescription->gameID; -} - uint32 DrasculaEngine::getFeatures() const { - return _gameDescription->features; + return _gameDescription->desc.flags; } -Common::Platform DrasculaEngine::getPlatform() const { - return _gameDescription->desc.platform; +Common::Language DrasculaEngine::getLanguage() const { + return _gameDescription->desc.language; } -uint16 DrasculaEngine::getVersion() const { - return _gameDescription->version; +void DrasculaEngine::loadArchives() { + const Common::ADGameFileDescription *ag; + + if (getFeatures() & GF_PACKED) { + for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++) + _arj.registerArchive(ag->fileName); + } + + _arj.enableFallback(true); } } @@ -75,53 +73,129 @@ static const DrasculaGameDescription gameDescriptions[] = { { "drascula", 0, - AD_ENTRY1("14.ald", "09b2735953edcd43af115c65ae00b10e"), + AD_ENTRY1s("14.ald", "09b2735953edcd43af115c65ae00b10e", 1595), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, - 0, - 0, - 0, - 0, }, -/* + + { + // Drascula English version (original packed files) + { + "drascula", + 0, + AD_ENTRY1s("packet.001", "c6a8697396e213a18472542d5f547cb4", 32847563), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_KEEPMATCH | GF_PACKED + }, + }, + + { + // Drascula German version (original packed files) + { + "drascula", + 0, + { + {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563}, + {"packet.003", 0, "e8f4dc6091037329bab4ddb1cba35807", 719728}, + {NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + GF_PACKED + }, + }, + + { + // Drascula French version (original packed files) + { + "drascula", + 0, + { + {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563}, + {"packet.002", 0, "4401123400f22f212b89f15fb4b43013", 721122}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + GF_PACKED + }, + }, + + { + // Drascula Spanish version (original packed version) + { + "drascula", + 0, + AD_ENTRY1s("packet.001", "3c971aba65a037d29d0b479cad6f5943", 31702652), + Common::ES_ESP, + Common::kPlatformPC, + GF_PACKED + }, + }, + { // Drascula Spanish version { "drascula", 0, - AD_ENTRY1("14.ald", "0746ed1a5cc8d9728f790c29813f4b43"), + AD_ENTRY1s("14.ald", "0746ed1a5cc8d9728f790c29813f4b43", 23059), Common::ES_ESP, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, - 0, - 0, - 0, - 0, - },*/ + }, - { AD_TABLE_END_MARKER, 0, 0, 0, 0 } -}; + { + // Drascula German version + { + "drascula", + 0, + AD_ENTRY1s("14.ald", "72e46089033d56bad1c179ac36e2a9d2", 610), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + }, -/** - * The fallback game descriptor used by the Drascula engine's fallbackDetector. - * Contents of this struct are to be overwritten by the fallbackDetector. - */ -static DrasculaGameDescription g_fallbackDesc = { { - "", - "", - AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor - Common::UNK_LANG, - Common::kPlatformPC, - Common::ADGF_NO_FLAGS + // Drascula French version + { + "drascula", + 0, + AD_ENTRY1s("14.ald", "eeeee96b82169003630e08992248296c", 608), + Common::FR_FRA, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, }, - 0, - 0, - 0, - 0, + + { + // Drascula Italian version (original packed version) + { + "drascula", + 0, + AD_ENTRY1s("packet.001", "0253e924af223f5fe52537023385159b", 32564209), + Common::IT_ITA, + Common::kPlatformPC, + GF_PACKED + }, + }, + { + // Drascula Italian version + { + "drascula", + 0, + AD_ENTRY1s("14.ald", "02b49a18328d0bf2efe6ba658c9c7a1d", 2098), + Common::IT_ITA, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + }, + + { AD_TABLE_END_MARKER } }; } // End of namespace Drascula @@ -158,9 +232,6 @@ public: } virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; - - const Common::ADGameDescription *fallbackDetect(const FSList *fslist) const; - }; bool DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const { @@ -171,20 +242,6 @@ bool DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Co return gd != 0; } -const Common::ADGameDescription *DrasculaMetaEngine::fallbackDetect(const FSList *fslist) const { - // Set the default values for the fallback descriptor's ADGameDescription part. - Drascula::g_fallbackDesc.desc.language = Common::UNK_LANG; - Drascula::g_fallbackDesc.desc.platform = Common::kPlatformPC; - Drascula::g_fallbackDesc.desc.flags = Common::ADGF_NO_FLAGS; - - // Set default values for the fallback descriptor's DrasculaGameDescription part. - Drascula::g_fallbackDesc.gameID = 0; - Drascula::g_fallbackDesc.features = 0; - Drascula::g_fallbackDesc.version = 0; - - return (const Common::ADGameDescription *)&Drascula::g_fallbackDesc; -} - #if PLUGIN_ENABLED_DYNAMIC(DRASCULA) REGISTER_PLUGIN_DYNAMIC(DRASCULA, PLUGIN_TYPE_ENGINE, DrasculaMetaEngine); #else diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 89bb6e530d..1cbe2ae0e1 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -58,13 +58,6 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - const GameSettings *g; - - const char *gameid = ConfMan.get("gameid").c_str(); - for (g = drasculaSettings; g->gameid; ++g) - if (!scumm_stricmp(g->gameid, gameid)) - _gameId = g->id; - _rnd = new Common::RandomSource(); syst->getEventManager()->registerRandomSource(*_rnd, "drascula"); @@ -77,35 +70,38 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam DrasculaEngine::~DrasculaEngine() { delete _rnd; -} -static const int x_obj[44] = {0, X_OBJ1, X_OBJ2, X_OBJ3, X_OBJ4, X_OBJ5, X_OBJ6, X_OBJ7, X_OBJ8, X_OBJ9, X_OBJ10, - X_OBJ11, X_OBJ12, X_OBJ13, X_OBJ14, X_OBJ15, X_OBJ16, X_OBJ17, X_OBJ18, X_OBJ19, X_OBJ20, - X_OBJ21, X_OBJ22, X_OBJ23, X_OBJ24, X_OBJ25, X_OBJ26, X_OBJ27, X_OBJ28, X_OBJ29, X_OBJ30, - X_OBJ31, X_OBJ32, X_OBJ33, X_OBJ34, X_OBJ35, X_OBJ36, X_OBJ37, X_OBJ38, X_OBJ39, X_OBJ40, - X_OBJ41, X_OBJ42, X_OBJ43}; -static const int y_obj[44] = {0, Y_OBJ1, Y_OBJ2, Y_OBJ3, Y_OBJ4, Y_OBJ5, Y_OBJ6, Y_OBJ7, Y_OBJ8, Y_OBJ9, Y_OBJ10, - Y_OBJ11, Y_OBJ12, Y_OBJ13, Y_OBJ14, Y_OBJ15, Y_OBJ16, Y_OBJ17, Y_OBJ18, Y_OBJ19, Y_OBJ20, - Y_OBJ21, Y_OBJ22, Y_OBJ23, Y_OBJ24, Y_OBJ25, Y_OBJ26, Y_OBJ27, Y_OBJ28, Y_OBJ29, Y_OBJ30, - Y_OBJ31, Y_OBJ32, Y_OBJ33, Y_OBJ34, Y_OBJ35, Y_OBJ36, Y_OBJ37, Y_OBJ38, Y_OBJ39, Y_OBJ40, - Y_OBJ41, Y_OBJ42, Y_OBJ43}; -static const int x_pol[44] = {0, 1, 42, 83, 124, 165, 206, 247, 83, 1, 206, - 1, 42, 83, 124, 165, 206, 247, 83, 1, 206, - 247, 83, 165, 1, 206, 42, 124, 83, 1, 247, - 83, 165, 1, 206, 42, 124, 83, 1, 247, 42, - 1, 165, 206}; -static const int y_pol[44] = {0, 1, 1, 1, 1, 1, 1, 1, 27, 27, 1, - 27, 27, 27, 27, 27, 27, 27, 1, 1, 27, - 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, - 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, - 27, 1, 1}; -static const int x_barra[] = {6, 51, 96, 141, 186, 232, 276, 321}; -static const int x1d_menu[] = {280, 40, 80, 120, 160, 200, 240, 0, 40, 80, 120, - 160, 200, 240, 0, 40, 80, 120, 160, 200, 240, 0, - 40, 80, 120, 160, 200, 240, 0}; -static const int y1d_menu[] = {0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, - 50, 50, 50, 50, 50, 50, 50, 75, 75, 75, 75, 75, 75, 75, 100}; -static int frame_x[20] = {43, 87, 130, 173, 216, 259}; + free(_charMap); + free(_itemLocations); + free(_polX); + free(_polY); + free(_verbBarX); + free(_x1d_menu); + free(_y1d_menu); + free(_frameX); + free(_candleX); + free(_candleY); + free(_pianistX); + free(_drunkX); + free(_roomPreUpdates); + free(_roomUpdates); + free(_roomActions); + freeTexts(_text); + freeTexts(_textd); + freeTexts(_textb); + freeTexts(_textbj); + freeTexts(_texte); + freeTexts(_texti); + freeTexts(_textl); + freeTexts(_textp); + freeTexts(_textt); + freeTexts(_textvb); + freeTexts(_textsys); + freeTexts(_texthis); + freeTexts(_textverbs); + freeTexts(_textmisc); + freeTexts(_textd1); +} int DrasculaEngine::init() { // Initialize backend @@ -114,764 +110,469 @@ int DrasculaEngine::init() { _system->initSize(320, 200); _system->endGFXTransaction(); + switch (getLanguage()) { + case Common::EN_ANY: + _lang = 0; + break; + case Common::ES_ESP: + _lang = 1; + break; + case Common::DE_DEU: + _lang = 2; + break; + case Common::FR_FRA: + _lang = 3; + break; + case Common::IT_ITA: + _lang = 4; + break; + default: + warning("Unknown game language. Falling back to English"); + _lang = 0; + } + + _charMap = 0; + _itemLocations = 0; + _polX = 0; + _polY = 0; + _verbBarX = 0; + _x1d_menu = 0; + _y1d_menu = 0; + _frameX = 0; + _candleX = 0; + _candleY = 0; + _pianistX = 0; + _drunkX = 0; + _roomPreUpdates = 0; + _roomUpdates = 0; + _roomActions = 0; + _text = 0; + _textd = 0; + _textb = 0; + _textbj = 0; + _texte = 0; + _texti = 0; + _textl = 0; + _textp = 0; + _textt = 0; + _textvb = 0; + _textsys = 0; + _texthis = 0; + _textverbs = 0; + _textmisc = 0; + _textd1 = 0; + + if (!loadDrasculaDat()) + return 1; + + setupRoomsTable(); + loadArchives(); + return 0; } int DrasculaEngine::go() { - num_ejec = 1; // values from 1 to 6 will start each part of game + currentChapter = 1; // values from 1 to 6 will start each part of game hay_que_load = 0; for (;;) { + int i; + VGA = (byte *)malloc(320 * 200); memset(VGA, 0, 64000); - lleva_objeto = 0; - menu_bar = 0; menu_scr = 0; hay_nombre = 0; + takeObject = 0; + menuBar = 0; menuScreen = 0; hasName = 0; frame_y = 0; - hare_x = -1; hare_se_mueve = 0; sentido_hare = 3; num_frame = 0; hare_se_ve = 1; - comprueba_flags = 1; - rompo = 0; rompo2 = 0; - anda_a_objeto = 0; - paso_x = PASO_HARE_X; paso_y = PASO_HARE_Y; - alto_hare = ALTO_PERSONAJE; ancho_hare = ANCHO_PERSONAJE; alto_pies = PIES_HARE; - alto_talk = ALTO_TALK_HARE; ancho_talk = ANCHO_TALK_HARE; - hay_respuesta = 0; - conta_ciego_vez = 0; - cambio_de_color = 0; - rompo_y_salgo = 0; - vb_x = 120; sentido_vb = 1; vb_se_mueve = 0; frame_vb = 1; - frame_piano = 0; - frame_borracho = 0; - frame_velas = 0; - cont_sv = 0; + curX = -1; characterMoved = 0; trackProtagonist = 3; num_frame = 0; hare_se_ve = 1; + checkFlags = 1; + doBreak = 0; + walkToObject = 0; + stepX = STEP_X; stepY = STEP_Y; + curHeight = CHARACTER_HEIGHT; curWidth = CHARACTER_WIDTH; feetHeight = FEET_HEIGHT; + talkHeight = TALK_HEIGHT; talkWidth = TALK_WIDTH; + hasAnswer = 0; + savedTime = 0; + changeColor = 0; + breakOut = 0; + vonBraunX = 120; trackVonBraun = 1; vonBraunHasMoved = 0; + framesWithoutAction = 0; term_int = 0; - corta_musica = 0; - hay_seleccion = 0; - Leng = 0; + musicStopped = 0; + selectionMade = 0; UsingMem = 0; - GlobalSpeed = 0; - frame_ciego = 0; - frame_ronquido = 0; - frame_murcielago = 0; - c_mirar = 0; - c_poder = 0; - ald = NULL; - sku = NULL; - - asigna_memoria(); - - hay_sb = 1; - con_voces = 0; - hay_seleccion = 0; - - if (num_ejec != 6) { - loadPic("95.alg"); - decompressPic(dir_mesa, 1); - } - - if (num_ejec == 1) { - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - } else if (num_ejec == 2) { - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("pts.alg"); - decompressPic(dir_dibujo2, 1); - } else if (num_ejec == 3) { - loadPic("aux13.alg"); - decompressPic(dir_dibujo1, COMPLETA); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - } else if (num_ejec == 4) { - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); + globalSpeed = 0; + curExcuseLook = 0; + curExcuseAction = 0; + roomNumber = 0; + + for (i = 0; i < 8; i++) + actorFrames[i] = 0; + actorFrames[kFrameVonBraun] = 1; + + allocMemory(); + + withVoices = 0; + selectionMade = 0; + + if (currentChapter != 6) + loadPic(95, tableSurface); + + if (currentChapter == 1) { + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(99, backSurface); + loadPic(97, extraSurface); + } else if (currentChapter == 2) { + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic("pts.alg", drawSurface2); + } else if (currentChapter == 3) { + loadPic("aux13.alg", bgSurface, COMPLETE_PAL); + loadPic(96, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); + } else if (currentChapter == 4) { + loadPic(96, frontSurface, COMPLETE_PAL); if (hay_que_load == 0) - animation_rayo(); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); + animation_ray(); + loadPic(96, frontSurface); clearRoom(); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - } else if (num_ejec == 5) { - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - } else if (num_ejec == 6) { - x_igor = 105, y_igor = 85, sentido_igor = 1; - x_dr = 62, y_dr = 99, sentido_dr = 1; - frame_pen = 0; + loadPic(99, backSurface); + loadPic(97, extraSurface); + } else if (currentChapter == 5) { + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(97, extraSurface); + loadPic(99, backSurface); + } else if (currentChapter == 6) { + igorX = 105, igorY = 85, trackIgor = 1; + drasculaX = 62, drasculaY = 99, trackDrascula = 1; + actorFrames[kFramePendulum] = 0; flag_tv = 0; - dir_pendulo = dir_dibujo3; + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(99, backSurface); + loadPic(97, extraSurface); + loadPic(95, tableSurface); + } + memset(iconName, 0, sizeof(iconName)); - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); + for (i = 0; i < 6; i++) + strcpy(iconName[i + 1], _textverbs[_lang][i]); - loadPic("95.alg"); - decompressPic(dir_mesa, 1); - } - memset(nombre_icono, 0, sizeof(nombre_icono)); - strcpy(nombre_icono[1], "look"); - strcpy(nombre_icono[2], "take"); - strcpy(nombre_icono[3], "open"); - strcpy(nombre_icono[4], "close"); - strcpy(nombre_icono[5], "talk"); - strcpy(nombre_icono[6], "push"); - - paleta_hare(); - if (!escoba()) { - salir_al_dos(0); + assignDefaultPalette(); + if (!runCurrentChapter()) { + endChapter(); break; } - salir_al_dos(0); - if (num_ejec == 6) + endChapter(); + if (currentChapter == 6) break; - num_ejec++; + currentChapter++; } return 0; } -void DrasculaEngine::salir_al_dos(int r) { - if (hay_sb == 1) - ctvd_end(); +void DrasculaEngine::endChapter() { + stopSound(); clearRoom(); - Negro(); + black(); MusicFadeout(); - stopmusic(); - libera_memoria(); + stopMusic(); + freeMemory(); free(VGA); } -void DrasculaEngine::asigna_memoria() { - dir_zona_pantalla = (byte *)malloc(64000); - assert(dir_zona_pantalla); - dir_dibujo1 = (byte *)malloc(64000); - assert(dir_dibujo1); - dir_hare_fondo = (byte *)malloc(64000); - assert(dir_hare_fondo); - dir_dibujo3 = (byte *)malloc(64000); - assert(dir_dibujo3); - dir_dibujo2 = (byte *)malloc(64000); - assert(dir_dibujo2); - dir_mesa = (byte *)malloc(64000); - assert(dir_mesa); - dir_hare_dch = (byte *)malloc(64000); - assert(dir_hare_dch); - dir_hare_frente = (byte *)malloc(64000); - assert(dir_hare_frente); -} - -void DrasculaEngine::libera_memoria() { - free(dir_zona_pantalla); - free(dir_dibujo1); - free(dir_hare_fondo); - free(dir_dibujo2); - free(dir_mesa); - free(dir_dibujo3); - free(dir_hare_dch); - free(dir_hare_frente); -} - -void DrasculaEngine::loadPic(const char *NamePcc) { - unsigned int con, x = 0; - unsigned int fExit = 0; - byte ch, rep; - Common::File file; - byte *auxPun; - - file.open(NamePcc); - if (!file.isOpen()) - error("missing game data %s %c", NamePcc, 7); - - Buffer_pcx = (byte *)malloc(65000); - auxPun = Buffer_pcx; - file.seek(128); - while (!fExit) { - ch = file.readByte(); - rep = 1; - if ((ch & 192) == 192) { - rep = (ch & 63); - ch = file.readByte(); - } - for (con = 0; con < rep; con++) { - *auxPun++ = ch; - x++; - if (x > 64000) - fExit = 1; - } - } - - file.read(cPal, 768); - file.close(); -} - -void DrasculaEngine::decompressPic(byte *dir_escritura, int plt) { - memcpy(dir_escritura, Buffer_pcx, 64000); - free(Buffer_pcx); - asigna_rgb((byte *)cPal, plt); - if (plt > 1) - funde_rgb(plt); -} - -void DrasculaEngine::paleta_hare() { - int color, componente; - - for (color = 235; color < 253; color++) - for (componente = 0; componente < 3; componente++) - palHare[color][componente] = palJuego[color][componente]; - -} - -void DrasculaEngine::hare_oscuro() { - int color, componente; - - for (color = 235; color < 253; color++ ) - for (componente = 0; componente < 3; componente++) - palJuego[color][componente] = palHareOscuro[color][componente]; - - ActualizaPaleta(); -} - -void DrasculaEngine::asigna_rgb(byte *dir_lectura, int plt) { - int x, cnt = 0; - - for (x = 0; x < plt; x++) { - palJuego[x][0] = dir_lectura[cnt++] / 4; - palJuego[x][1] = dir_lectura[cnt++] / 4; - palJuego[x][2] = dir_lectura[cnt++] / 4; - } - ActualizaPaleta(); -} - -void DrasculaEngine::funde_rgb(int plt) {} - -void DrasculaEngine::Negro() { - int color, componente; - DacPalette256 palNegra; - - for (color = 0; color < 256; color++) - for (componente = 0; componente < 3; componente++) - palNegra[color][componente] = 0; - - palNegra[254][0] = 0x3F; - palNegra[254][1] = 0x3F; - palNegra[254][2] = 0x15; - - setvgapalette256((byte *)&palNegra); -} - -void DrasculaEngine::ActualizaPaleta() { - setvgapalette256((byte *)&palJuego); -} - -void DrasculaEngine::setvgapalette256(byte *PalBuf) { - byte pal[256 * 4]; - int i; - - for (i = 0; i < 256; i++) { - pal[i * 4 + 0] = PalBuf[i * 3 + 0] * 4; - pal[i * 4 + 1] = PalBuf[i * 3 + 1] * 4; - pal[i * 4 + 2] = PalBuf[i * 3 + 2] * 4; - pal[i * 4 + 3] = 0; - } - _system->setPalette(pal, 0, 256); - _system->updateScreen(); -} - -void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int Ancho, - int Alto, byte *Origen, byte *Destino) { - int x; - Destino += xdes + ydes * 320; - Origen += xorg + yorg * 320; - for (x = 0; x < Alto; x++) { - memcpy(Destino, Origen, Ancho); - Destino += 320; - Origen += 320; - } -} - -void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int Ancho, - int Alto, byte *Origen, byte *Destino) { - int y, x; - - Destino += xdes + ydes * 320; - Origen += xorg + yorg * 320; - - for (y = 0; y < Alto; y++) - for (x = 0; x < Ancho; x++) - if (Origen[x + y * 320] != 255) - Destino[x + y * 320] = Origen[x + y * 320]; -} - -void DrasculaEngine::copyRectClip(int *Array, byte *Origen, byte *Destino) { - int y, x; - int xorg = Array[0]; - int yorg = Array[1]; - int xdes = Array[2]; - int ydes = Array[3]; - int Ancho = Array[4]; - int Alto = Array[5]; - - if (ydes < 0) { - yorg += -ydes; - Alto += ydes; - ydes = 0; - } - if (xdes < 0) { - xorg += -xdes; - Ancho += xdes; - xdes = 0; - } - if ((xdes + Ancho) > 319) - Ancho -= (xdes + Ancho) - 320; - if ((ydes + Alto) > 199) - Alto -= (ydes + Alto) - 200; - - Destino += xdes + ydes * 320; - Origen += xorg + yorg * 320; - - for (y = 0; y < Alto; y++) - for (x = 0; x < Ancho; x++) - if (Origen[x + y * 320] != 255) - Destino[x + y * 320] = Origen[x + y * 320]; -} - -void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int Ancho, int Alto, byte *Buffer) { - int x; - byte *ptr = VGA; - - ptr += xdes + ydes * 320; - Buffer += xorg + yorg * 320; - for (x = 0; x < Alto; x++) { - memcpy(ptr, Buffer, Ancho); - ptr += 320; - Buffer += 320; - } - - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - _system->updateScreen(); -} - -bool DrasculaEngine::escoba() { +bool DrasculaEngine::runCurrentChapter() { int n; - dir_texto = dir_mesa; + if (_lang == kSpanish) + textSurface = extraSurface; + else + textSurface = tableSurface; - musica_antes = -1; + previousMusic = -1; - if (num_ejec != 2) { + if (currentChapter != 2) { int soc = 0; for (n = 0; n < 6; n++) { - soc = soc + ANCHO_PERSONAJE; - frame_x[n] = soc; + soc = soc + CHARACTER_WIDTH; + _frameX[n] = soc; } } for (n = 1; n < 43; n++) - objetos_que_tengo[n] = 0; + inventoryObjects[n] = 0; - for (n = 0; n < NUM_BANDERAS; n++) + for (n = 0; n < NUM_FLAGS; n++) flags[n] = 0; - if (num_ejec == 2) { + if (currentChapter == 2) { flags[16] = 1; flags[17] = 1; flags[27] = 1; } for (n = 1; n < 7; n++) - objetos_que_tengo[n] = n; + inventoryObjects[n] = n; - if (num_ejec == 1) { - agarra_objeto(28); - buffer_teclado(); + if (currentChapter == 1) { + pickObject(28); if (hay_que_load == 0) animation_1_1(); - sin_verbo(); - loadPic("2aux62.alg"); - decompressPic(dir_dibujo2, 1); - sentido_hare = 1; - obj_saliendo = 104; + withoutVerb(); + loadPic("2aux62.alg", drawSurface2); + trackProtagonist = 1; + objExit = 104; if (hay_que_load != 0) { - if (!para_cargar(nom_partida)) { + if (!loadGame(saveName)) { return true; } } else { - carga_escoba("62.ald"); - hare_x = -20; - hare_y = 56; - lleva_al_hare(65, 145); - } - } else if (num_ejec == 2) { - suma_objeto(28); - buffer_teclado(); - sentido_hare = 3; - obj_saliendo = 162; + enterRoom(62); + curX = -20; + curY = 56; + gotoObject(65, 145); + } + } else if (currentChapter == 2) { + addObject(kItemPhone); + trackProtagonist = 3; + objExit = 162; if (hay_que_load == 0) - carga_escoba("14.ald"); + enterRoom(14); else { - if (!para_cargar(nom_partida)) { + if (!loadGame(saveName)) { return true; } } - } else if (num_ejec == 3) { - suma_objeto(28); - suma_objeto(11); - suma_objeto(14); - suma_objeto(22); - suma_objeto(9); - suma_objeto(20); - suma_objeto(19); + } else if (currentChapter == 3) { + addObject(kItemPhone); + addObject(kItemEarplugs); + addObject(kItemSickle); + addObject(kItemHandbag); + addObject(kItemCross); + addObject(kItemReefer); + addObject(kItemOneCoin); flags[1] = 1; - buffer_teclado(); - sentido_hare = 1; - obj_saliendo = 99; + trackProtagonist = 1; + objExit = 99; if (hay_que_load == 0) - carga_escoba("20.ald"); + enterRoom(20); else { - if (!para_cargar(nom_partida)) { + if (!loadGame(saveName)) { return true; } } - } else if (num_ejec == 4) { - suma_objeto(28); - suma_objeto(9); - suma_objeto(20); - suma_objeto(22); - buffer_teclado(); - obj_saliendo = 100; + // From here onwards the items have different IDs + } else if (currentChapter == 4) { + addObject(kItemPhone2); + addObject(kItemCross2); + addObject(kItemReefer2); + addObject(kItemOneCoin2); + objExit = 100; if (hay_que_load == 0) { - carga_escoba("21.ald"); - sentido_hare = 0; - hare_x = 235; - hare_y = 164; + enterRoom(21); + trackProtagonist = 0; + curX = 235; + curY = 164; } else { - if (!para_cargar(nom_partida)) { + if (!loadGame(saveName)) { return true; } } - } else if (num_ejec == 5) { - suma_objeto(28); - suma_objeto(7); - suma_objeto(9); - suma_objeto(11); - suma_objeto(13); - suma_objeto(14); - suma_objeto(15); - suma_objeto(17); - suma_objeto(20); - buffer_teclado(); - sentido_hare = 1; - obj_saliendo = 100; + } else if (currentChapter == 5) { + addObject(28); + addObject(7); + addObject(9); + addObject(11); + addObject(13); + addObject(14); + addObject(15); + addObject(17); + addObject(20); + trackProtagonist = 1; + objExit = 100; if (hay_que_load == 0) { - carga_escoba("45.ald"); + enterRoom(45); } else { - if (!para_cargar(nom_partida)) { + if (!loadGame(saveName)) { return true; } } - } else if (num_ejec == 6) { - suma_objeto(28); - suma_objeto(9); + } else if (currentChapter == 6) { + addObject(28); + addObject(9); - buffer_teclado(); - sentido_hare = 1; - obj_saliendo = 104; + trackProtagonist = 1; + objExit = 104; if (hay_que_load == 0) { - carga_escoba("58.ald"); + enterRoom(58); animation_1_6(); } else { - if (!para_cargar(nom_partida)) { + if (!loadGame(saveName)) { return true; } - loadPic("auxdr.alg"); - decompressPic(dir_dibujo2, 1); + loadPic("auxdr.alg", drawSurface2); + } + } + + while (1) { + if (characterMoved == 0) { + stepX = STEP_X; + stepY = STEP_Y; + } + if (characterMoved == 0 && walkToObject == 1) { + trackProtagonist = trackFinal; + walkToObject = 0; + } + + if (currentChapter == 2) { + // NOTE: the checks for room number 14 below are a hack used in the original + // game, and move the character to a place where his feet are not drawn above + // the pianist's head. Originally, walkToObject was not updated properly, which + // lead to an incorrect setting of the protagonist's tracking flag (above). This + // made the character start walking off screen, as his actual position was + // different than the displayed one + if (roomNumber == 3 && (curX == 279) && (curY + curHeight == 101)) { + animation_1_2(); + } else if (roomNumber == 14 && (curX == 214) && (curY + curHeight == 121)) { + walkToObject = 1; + gotoObject(190, 130); + } else if (roomNumber == 14 && (curX == 246) && (curY + curHeight == 112)) { + walkToObject = 1; + gotoObject(190, 130); + } } - } - -bucles: - if (hare_se_mueve == 0) { - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - } - if (hare_se_mueve == 0 && anda_a_objeto == 1) { - sentido_hare = sentido_final; - anda_a_objeto = 0; - } - - if (num_ejec == 2) { - if ((!strcmp(num_room, "3.alg")) && (hare_x == 279) && (hare_y + alto_hare == 101)) - animation_1_2(); - else if ((!strcmp(num_room, "14.alg")) && (hare_x == 214) && (hare_y + alto_hare == 121)) - lleva_al_hare(190, 130); - else if ((!strcmp(num_room, "14.alg")) && (hare_x == 246) && (hare_y + alto_hare == 112)) - lleva_al_hare(190, 130); - } - - mueve_cursor(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - if (num_ejec == 2) { - if (music_status() == 0 && musica_room != 0) - playmusic(musica_room); - } else { - if (music_status() == 0) - playmusic(musica_room); - } - - MirarRaton(); - - if (menu_scr == 0 && lleva_objeto == 1) - comprueba_objetos(); - - if (boton_dch == 1 && menu_scr == 1) { - delay(100); - if (num_ejec == 2) - loadPic(fondo_y_menu); - else - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - setvgapalette256((byte *)&palJuego); - menu_scr = 0; - espera_soltar(); - if (num_ejec != 3) - cont_sv = 0; - } - if (boton_dch == 1 && menu_scr == 0) { - delay(100); - hare_se_mueve = 0; - if (sentido_hare == 2) - sentido_hare = 1; - if (num_ejec == 4) - loadPic("icons2.alg"); - else if (num_ejec == 5) - loadPic("icons3.alg"); - else if (num_ejec == 6) - loadPic("iconsp.alg"); - else - loadPic("icons.alg"); - decompressPic(dir_hare_fondo, 1); - menu_scr = 1; - espera_soltar(); - sin_verbo(); - if (num_ejec != 3) - cont_sv = 0; - } - - if (boton_izq == 1 && menu_bar == 1) { - delay(100); - elige_en_barra(); - if (num_ejec != 3) - cont_sv = 0; - } else if (boton_izq == 1 && lleva_objeto == 0) { - delay(100); - if (comprueba1()) - return true; - if (num_ejec != 3) - cont_sv = 0; - } else if (boton_izq == 1 && lleva_objeto == 1) { - if (comprueba2()) - return true; - if (num_ejec != 3) - cont_sv = 0; - } - - if (y_raton < 24 && menu_scr == 0) - menu_bar = 1; - else - menu_bar = 0; - - Common::KeyCode key = getscan(); - if (key == Common::KEYCODE_F1 && menu_scr == 0) { - elige_verbo(1); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F2 && menu_scr == 0) { - elige_verbo(2); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F3 && menu_scr == 0) { - elige_verbo(3); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F4 && menu_scr == 0) { - elige_verbo(4); - cont_sv = 0; - } else if (key == Common::KEYCODE_F5 && menu_scr == 0) { - elige_verbo(5); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F6 && menu_scr == 0) { - elige_verbo(6); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F9) { - mesa(); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F10) { - if (!saves()) - return true; - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_F8) { - sin_verbo(); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_v) { - con_voces = 1; - print_abc(_textsys[_lang][2], 96, 86); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - delay(1410); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_t) { - con_voces = 0; - print_abc(_textsys[_lang][3], 94, 86); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - delay(1460); - if (num_ejec != 3) - cont_sv = 0; - } else if (key == Common::KEYCODE_ESCAPE) { - if (!confirma_salir()) - return false; - if (num_ejec != 3) - cont_sv = 0; - } else if (num_ejec == 6 && key == Common::KEYCODE_0 && !strcmp(num_room, "61.alg")) { - loadPic("alcbar.alg"); - decompressPic(dir_dibujo1, 255); - } else if (cont_sv == 1500) { - salva_pantallas(); - if (num_ejec != 3) - cont_sv = 0; - } else { - if (num_ejec != 3) - cont_sv++; - } - goto bucles; -} - -void DrasculaEngine::agarra_objeto(int objeto) { - if (num_ejec == 6) - loadPic("iconsp.alg"); - else if (num_ejec == 4) - loadPic("icons2.alg"); - else if (num_ejec == 5) - loadPic("icons3.alg"); - else - loadPic("icons.alg"); - decompressPic(dir_hare_fondo, 1); - elige_objeto(objeto); - if (num_ejec == 2) - loadPic(fondo_y_menu); - else - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); -} - -void DrasculaEngine::elige_objeto(int objeto) { - if (num_ejec == 5) { - if (lleva_objeto == 1 && menu_scr == 0 && objeto_que_lleva != 16) - suma_objeto(objeto_que_lleva); - } else { - if (lleva_objeto == 1 && menu_scr == 0) - suma_objeto(objeto_que_lleva); - } - copyBackground(x1d_menu[objeto], y1d_menu[objeto], 0, 0, ANCHOBJ,ALTOBJ, dir_hare_fondo, dir_dibujo3); - lleva_objeto = 1; - objeto_que_lleva = objeto; -} -int DrasculaEngine::resta_objeto(int osj) { - int h, q = 0; + moveCursor(); + updateScreen(); - for (h = 1; h < 43; h++) { - if (objetos_que_tengo[h] == osj) { - objetos_que_tengo[h] = 0; - q = 1; - break; + if (currentChapter == 2) { + if (musicStatus() == 0 && roomMusic != 0) + playMusic(roomMusic); + } else { + if (musicStatus() == 0) + playMusic(roomMusic); } - } - - if (q == 1) - return 0; - else - return 1; -} -void DrasculaEngine::sin_verbo() { - int c = 171; - if (menu_scr == 1) - c = 0; - if (num_ejec == 5) { - if (lleva_objeto == 1 && objeto_que_lleva != 16) - suma_objeto(objeto_que_lleva); - } else { - if (lleva_objeto == 1) - suma_objeto(objeto_que_lleva); - } - copyBackground(0, c, 0, 0, ANCHOBJ,ALTOBJ, dir_hare_fondo, dir_dibujo3); + updateEvents(); - lleva_objeto = 0; - hay_nombre = 0; -} - -bool DrasculaEngine::para_cargar(char nom_game[]) { - musica_antes = musica_room; - menu_scr = 0; - if (num_ejec != 1) - clearRoom(); - if (!carga_partida(nom_game)) - return false; - if (num_ejec == 2 || num_ejec == 3 || num_ejec == 5) { - delete ald; - ald = NULL; - } - carga_escoba(datos_actuales); - sin_verbo(); + if (menuScreen == 0 && takeObject == 1) + checkObjects(); + + if (rightMouseButton == 1 && menuScreen == 1) { + delay(100); + if (currentChapter == 2) + loadPic(menuBackground, backSurface); + else + loadPic(99, backSurface); + setPalette((byte *)&gamePalette); + menuScreen = 0; + updateEvents(); + } + if (rightMouseButton == 1 && menuScreen == 0) { + delay(100); + characterMoved = 0; + if (trackProtagonist == 2) + trackProtagonist = 1; + if (currentChapter == 4) + loadPic("icons2.alg", backSurface); + else if (currentChapter == 5) + loadPic("icons3.alg", backSurface); + else if (currentChapter == 6) + loadPic("iconsp.alg", backSurface); + else + loadPic("icons.alg", backSurface); + menuScreen = 1; + updateEvents(); + withoutVerb(); + } - return true; -} + if (leftMouseButton == 1 && menuBar == 1) { + delay(100); + selectVerbFromBar(); + } else if (leftMouseButton == 1 && takeObject == 0) { + delay(100); + if (verify1()) + return true; + } else if (leftMouseButton == 1 && takeObject == 1) { + if (verify2()) + return true; + } -static char *getLine(Common::File *fp, char *buf, int len) { + menuBar = (mouseY < 24 && menuScreen == 0) ? 1 : 0; + + Common::KeyCode key = getScan(); + if (key == Common::KEYCODE_F1 && menuScreen == 0) { + selectVerb(1); + } else if (key == Common::KEYCODE_F2 && menuScreen == 0) { + selectVerb(2); + } else if (key == Common::KEYCODE_F3 && menuScreen == 0) { + selectVerb(3); + } else if (key == Common::KEYCODE_F4 && menuScreen == 0) { + selectVerb(4); + } else if (key == Common::KEYCODE_F5 && menuScreen == 0) { + selectVerb(5); + } else if (key == Common::KEYCODE_F6 && menuScreen == 0) { + selectVerb(6); + } else if (key == Common::KEYCODE_F9) { + volumeControls(); + } else if (key == Common::KEYCODE_F10) { + if (!saveLoadScreen()) + return true; + } else if (key == Common::KEYCODE_F8) { + withoutVerb(); + } else if (key == Common::KEYCODE_v) { + withVoices = 1; + print_abc(_textsys[_lang][2], 96, 86); + updateScreen(); + delay(1410); + } else if (key == Common::KEYCODE_t) { + withVoices = 0; + print_abc(_textsys[_lang][3], 94, 86); + updateScreen(); + delay(1460); + } else if (key == Common::KEYCODE_ESCAPE) { + if (!confirmExit()) + return false; + } else if (currentChapter == 6 && key == Common::KEYCODE_0 && roomNumber == 61) { + loadPic("alcbar.alg", bgSurface, 255); + } + + if (leftMouseButton != 0 || rightMouseButton != 0 || key != 0) + if (currentChapter != 3) + framesWithoutAction = 0; + + if (framesWithoutAction == 15000) { + screenSaver(); + if (currentChapter != 3) + framesWithoutAction = 0; + } + + if (currentChapter != 3) + framesWithoutAction++; + + } +} + +char *DrasculaEngine::getLine(char *buf, int len) { byte c; char *b; for (;;) { b = buf; - while (!fp->eos()) { - c = ~fp->readByte(); + while (!_arj.eos()) { + c = ~_arj.readByte(); if (c == '\r') continue; - if (c == '\n') - break; - if (b - buf >= (len - 1)) + if (c == '\n' || b - buf >= (len - 1)) break; *b++ = c; } *b = '\0'; - if (fp->eos() && b == buf) + if (_arj.eos() && b == buf) return NULL; if (b != buf) break; @@ -879,473 +580,79 @@ static char *getLine(Common::File *fp, char *buf, int len) { return buf; } -void DrasculaEngine::carga_escoba(const char *nom_fich) { - int soc, l, martin = 0, obj_salir = 0; - float chiquez = 0, pequegnez = 0; - char pant1[20], pant2[20], pant3[20], pant4[20]; - char para_codificar[20]; - char buffer[256]; - - hay_nombre = 0; - - strcpy(para_codificar, nom_fich); - strcpy(datos_actuales, nom_fich); - - buffer_teclado(); - - ald = new Common::File; - ald->open(nom_fich); - if (!ald->isOpen()) { - error("missing data file"); - } - int size = ald->size(); - getLine(ald, buffer, size); - sscanf(buffer, "%s", num_room); - strcat(num_room, ".alg"); - - getLine(ald, buffer, size); - sscanf(buffer, "%d", &musica_room); - getLine(ald, buffer, size); - sscanf(buffer, "%s", roomDisk); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &nivel_osc); - - if (num_ejec == 2) { - getLine(ald, buffer, size); - sscanf(buffer, "%d", &martin); - if (martin == 0) - goto martini; - ancho_hare = martin; - getLine(ald, buffer, size); - sscanf(buffer, "%d",&alto_hare); - getLine(ald, buffer, size); - sscanf(buffer, "%d",&alto_pies); - getLine(ald, buffer, size); - sscanf(buffer, "%d",&paso_x); - getLine(ald, buffer, size); - sscanf(buffer, "%d",&paso_y); - - getLine(ald, buffer, size); - sscanf(buffer, "%s",pant1); - getLine(ald, buffer, size); - sscanf(buffer, "%s",pant2); - getLine(ald, buffer, size); - sscanf(buffer, "%s",pant3); - getLine(ald, buffer, size); - sscanf(buffer, "%s",pant4); - - loadPic(pant2); - decompressPic(dir_hare_dch, 1); - loadPic(pant1); - decompressPic(dir_hare_frente, 1); - loadPic(pant4); - decompressPic(dir_hare_fondo, 1); - - strcpy(fondo_y_menu, pant4); - } - -martini: - - getLine(ald, buffer, size); - sscanf(buffer, "%d", &objs_room); - - for (l = 0; l < objs_room; l++) { - getLine(ald, buffer, size); - sscanf(buffer, "%d", &num_obj[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%s", nombre_obj[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &x1[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &y1[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &x2[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &y2[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &sitiobj_x[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &sitiobj_y[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &sentidobj[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &visible[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &espuerta[l]); - if (espuerta[l] != 0) { - getLine(ald, buffer, size); - sscanf(buffer, "%s", alapantallakeva[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &x_alakeva[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &y_alakeva[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &sentido_alkeva[l]); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &alapuertakeva[l]); - puertas_cerradas(l); - } - } - - getLine(ald, buffer, size); - sscanf(buffer, "%d", &suelo_x1); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &suelo_y1); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &suelo_x2); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &suelo_y2); - - if (num_ejec != 2) { - getLine(ald, buffer, size); - sscanf(buffer, "%d", &lejos); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &cerca); - } - delete ald; - ald = NULL; - - if (num_ejec == 2) { - if (martin == 0) { - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - alto_hare = ALTO_PERSONAJE; - ancho_hare = ANCHO_PERSONAJE; - alto_pies = PIES_HARE; - loadPic("97.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - - strcpy(fondo_y_menu, "99.alg"); - } - } - - for (l = 0; l < objs_room; l++) { - if (num_obj[l] == obj_saliendo) - obj_salir = l; - } - - if (num_ejec == 2) { - if (hare_x == -1) { - hare_x = x_alakeva[obj_salir]; - hare_y = y_alakeva[obj_salir] - alto_hare; - } - hare_se_mueve = 0; - } - loadPic(roomDisk); - decompressPic(dir_dibujo3, 1); - - loadPic(num_room); - decompressPic(dir_dibujo1, MEDIA); - - copyBackground(0, 171, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3); - - color_hare(); - if (nivel_osc != 0) - funde_hare(nivel_osc); - paleta_hare_claro(); - color_hare(); - funde_hare(nivel_osc + 2); - paleta_hare_oscuro(); - - hare_claro(); - cambio_de_color = -1; - - if (num_ejec == 2) - color_abc(VERDE_CLARO); - - if (num_ejec != 2) { - for (l = 0; l <= suelo_y1; l++) - factor_red[l] = lejos; - for (l = suelo_y1; l <= 201; l++) - factor_red[l] = cerca; - - chiquez = (float)(cerca - lejos) / (float)(suelo_y2 - suelo_y1); - for (l = suelo_y1; l <= suelo_y2; l++) { - factor_red[l] = (int)(lejos + pequegnez); - pequegnez = pequegnez + chiquez; - } - } - - if (!strcmp(num_room, "24.alg")) { - for (l = suelo_y1 - 1; l > 74; l--) { - factor_red[l] = (int)(lejos - pequegnez); - pequegnez = pequegnez + chiquez; - } - } - - if (num_ejec == 5 && !strcmp(num_room, "54.alg")) { - for (l = suelo_y1 - 1; l > 84; l--) { - factor_red[l] = (int)(lejos - pequegnez); - pequegnez = pequegnez + chiquez; - } - } - - if (num_ejec != 2) { - if (hare_x == -1) { - hare_x = x_alakeva[obj_salir]; - hare_y = y_alakeva[obj_salir]; - alto_hare = (ALTO_PERSONAJE * factor_red[hare_y]) / 100; - ancho_hare = (ANCHO_PERSONAJE * factor_red[hare_y]) / 100; - hare_y = hare_y - alto_hare; - } else { - alto_hare = (ALTO_PERSONAJE * factor_red[hare_y]) / 100; - ancho_hare = (ANCHO_PERSONAJE * factor_red[hare_y]) / 100; - } - hare_se_mueve = 0; - } - - if (num_ejec == 2) { - soc = 0; - for (l = 0; l < 6; l++) { - soc = soc + ancho_hare; - frame_x[l] = soc; - } - } - - if (num_ejec == 5) - hare_se_ve = 1; - - actualiza_datos(); - - if (num_ejec == 1) - espuerta[7] = 0; - - if (num_ejec == 2) { - if (!strcmp(num_room, "14.alg") && flags[39] == 1) - musica_room = 16; - else if (!strcmp(num_room, "15.alg") && flags[39] == 1) - musica_room = 16; - if (!strcmp(num_room, "14.alg") && flags[5] == 1) - musica_room = 0; - else if (!strcmp(num_room, "15.alg") && flags[5] == 1) - musica_room = 0; - - if (musica_antes != musica_room && musica_room != 0) - playmusic(musica_room); - if (musica_room == 0) - stopmusic(); - } else { - if (musica_antes != musica_room && musica_room != 0) - playmusic(musica_room); - } - - if (num_ejec == 2) { - if ((!strcmp(num_room, "9.alg")) || (strcmp(num_room, "2.alg")) || (!strcmp(num_room, "14.alg")) || (!strcmp(num_room, "18.alg"))) - conta_ciego_vez = vez(); - } - if (num_ejec == 4) { - if (!strcmp(num_room, "26.alg")) - conta_ciego_vez = vez(); - } - - if (num_ejec == 4 && !strcmp(num_room, "24.alg") && flags[29] == 1) - animation_7_4(); - - if (num_ejec == 5) { - if (!strcmp(num_room, "45.alg")) - hare_se_ve = 0; - if (!strcmp(num_room, "49.alg") && flags[7] == 0) - animation_4_5(); - } - - updateRoom(); -} - -void DrasculaEngine::clearRoom() { - memset(VGA, 0, 64000); - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - _system->updateScreen(); +void DrasculaEngine::getIntFromLine(char *buf, int len, int* result) { + getLine(buf, len); + sscanf(buf, "%d", result); } -void DrasculaEngine::lleva_al_hare(int punto_x, int punto_y) { - if (num_ejec == 5 || num_ejec == 6) { - if (hare_se_ve == 0) { - hare_x = sitio_x; - hare_y = sitio_y; - goto fin; - } - } - sitio_x = punto_x; - sitio_y = punto_y; - empieza_andar(); - - for (;;) { - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if (hare_se_mueve == 0) - break; - } - - if (anda_a_objeto == 1) { - anda_a_objeto = 0; - sentido_hare = sentido_final; - } -fin: - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::mueve_cursor() { - int pos_cursor[8]; - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - pon_hare(); - updateRefresh(); - - if (!strcmp(texto_nombre, "hacker") && hay_nombre == 1) { - if (_color != ROJO && menu_scr == 0) - color_abc(ROJO); - } else if (menu_scr == 0 && _color != VERDE_CLARO) - color_abc(VERDE_CLARO); - if (hay_nombre == 1 && menu_scr == 0) - centra_texto(texto_nombre, x_raton, y_raton); - if (menu_scr == 1) - menu_sin_volcar(); - else if (menu_bar == 1) - barra_menu(); - - pos_cursor[0] = 0; - pos_cursor[1] = 0; - pos_cursor[2] = x_raton - 20; - pos_cursor[3] = y_raton - 17; - pos_cursor[4] = ANCHOBJ; - pos_cursor[5] = ALTOBJ; - copyRectClip(pos_cursor, dir_dibujo3, dir_zona_pantalla); +void DrasculaEngine::getStringFromLine(char *buf, int len, char* result) { + getLine(buf, len); + sscanf(buf, "%s", result); } -void DrasculaEngine::comprueba_objetos() { - int l, veo = 0; - - for (l = 0; l < objs_room; l++) { - if (x_raton > x1[l] && y_raton > y1[l] - && x_raton < x2[l] && y_raton < y2[l] - && visible[l] == 1 && espuerta[l] == 0) { - strcpy(texto_nombre, nombre_obj[l]); - hay_nombre = 1; - veo = 1; - } - } - - if (num_ejec == 2) { - if (x_raton > hare_x + 2 && y_raton > hare_y + 2 - && x_raton < hare_x + ancho_hare - 2 && y_raton < hare_y + alto_hare - 2) { - strcpy(texto_nombre, "hacker"); - hay_nombre = 1; - veo = 1; - } - } else { - if (x_raton > hare_x + 2 && y_raton > hare_y + 2 - && x_raton < hare_x + ancho_hare - 2 && y_raton < hare_y + alto_hare - 2 && veo == 0) { - strcpy(texto_nombre, "hacker"); - hay_nombre = 1; - veo = 1; - } - } - - if (veo == 0) - hay_nombre = 0; -} - -void DrasculaEngine::espera_soltar() { - update_events(); -} - -void DrasculaEngine::MirarRaton() { - update_events(); -} - -void DrasculaEngine::elige_en_barra() { - int n, num_verbo = -1; - - for (n = 0; n < 7; n++) - if (x_raton > x_barra[n] && x_raton < x_barra[n + 1]) - num_verbo = n; - - if (num_verbo < 1) - sin_verbo(); - else - elige_verbo(num_verbo); -} - -bool DrasculaEngine::comprueba1() { +bool DrasculaEngine::verify1() { int l; - if (menu_scr == 1) - saca_objeto(); + if (menuScreen == 1) + removeObject(); else { - for (l = 0; l < objs_room; l++) { - if (x_raton >= x1[l] && y_raton >= y1[l] - && x_raton <= x2[l] && y_raton <= y2[l] && rompo == 0) { - if (sal_de_la_habitacion(l)) + for (l = 0; l < numRoomObjs; l++) { + if (mouseX >= x1[l] && mouseY >= y1[l] + && mouseX <= x2[l] && mouseY <= y2[l] && doBreak == 0) { + if (exitRoom(l)) return true; - if (rompo == 1) + if (doBreak == 1) break; } } - if (x_raton > hare_x && y_raton > hare_y - && x_raton < hare_x + ancho_hare && y_raton < hare_y + alto_hare) - rompo = 1; - - for (l = 0; l < objs_room; l++) { - if (x_raton > x1[l] && y_raton > y1[l] - && x_raton < x2[l] && y_raton < y2[l] && rompo == 0) { - sitio_x = sitiobj_x[l]; - sitio_y = sitiobj_y[l]; - sentido_final = sentidobj[l]; - rompo = 1; - anda_a_objeto = 1; - empieza_andar(); + if (mouseX > curX && mouseY > curY + && mouseX < curX + curWidth && mouseY < curY + curHeight) + doBreak = 1; + + for (l = 0; l < numRoomObjs; l++) { + if (mouseX > x1[l] && mouseY > y1[l] + && mouseX < x2[l] && mouseY < y2[l] && doBreak == 0) { + roomX = roomObjX[l]; + roomY = roomObjY[l]; + trackFinal = trackObj[l]; + doBreak = 1; + walkToObject = 1; + startWalking(); } } - if (rompo == 0) { - sitio_x = x_raton; - sitio_y = y_raton; - - if (sitio_x < suelo_x1) - sitio_x = suelo_x1; - if (sitio_x > suelo_x2) - sitio_x = suelo_x2; - if (sitio_y < suelo_y1 + alto_pies) - sitio_y = suelo_y1 + alto_pies; - if (sitio_y > suelo_y2) - sitio_y = suelo_y2; - - empieza_andar(); + if (doBreak == 0) { + roomX = CLIP(mouseX, floorX1, floorX2); + roomY = CLIP(mouseY, floorY1 + feetHeight, floorY2); + startWalking(); } - rompo = 0; + doBreak = 0; } return false; } -bool DrasculaEngine::comprueba2() { +bool DrasculaEngine::verify2() { int l; - if (menu_scr == 1) { - if (coge_objeto()) + if (menuScreen == 1) { + if (pickupObject()) return true; } else { - if (!strcmp(texto_nombre, "hacker") && hay_nombre == 1) { - if (banderas(50)) + if (!strcmp(textName, "hacker") && hasName == 1) { + if (checkAction(50)) return true; } else { - for (l = 0; l < objs_room; l++) { - if (x_raton > x1[l] && y_raton > y1[l] - && x_raton < x2[l] && y_raton < y2[l] && visible[l] == 1) { - sentido_final = sentidobj[l]; - anda_a_objeto = 1; - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - if (banderas(num_obj[l])) + for (l = 0; l < numRoomObjs; l++) { + if (mouseX > x1[l] && mouseY > y1[l] + && mouseX < x2[l] && mouseY < y2[l] && visible[l] == 1) { + trackFinal = trackObj[l]; + walkToObject = 1; + gotoObject(roomObjX[l], roomObjY[l]); + if (checkAction(objectNum[l])) return true; - if (num_ejec == 4) + if (currentChapter == 4) break; } } @@ -1355,13 +662,13 @@ bool DrasculaEngine::comprueba2() { return false; } -Common::KeyCode DrasculaEngine::getscan() { - update_events(); +Common::KeyCode DrasculaEngine::getScan() { + updateEvents(); return _keyPressed.keycode; } -void DrasculaEngine::update_events() { +void DrasculaEngine::updateEvents() { Common::Event event; Common::EventManager *eventMan = _system->getEventManager(); @@ -1376,25 +683,25 @@ void DrasculaEngine::update_events() { _keyPressed.keycode = Common::KEYCODE_INVALID; break; case Common::EVENT_MOUSEMOVE: - x_raton = event.mouse.x; - y_raton = event.mouse.y; + mouseX = event.mouse.x; + mouseY = event.mouse.y; break; case Common::EVENT_LBUTTONDOWN: - boton_izq = 1; + leftMouseButton = 1; break; case Common::EVENT_LBUTTONUP: - boton_izq = 0; + leftMouseButton = 0; break; case Common::EVENT_RBUTTONDOWN: - boton_dch = 1; + rightMouseButton = 1; break; case Common::EVENT_RBUTTONUP: - boton_dch = 0; + rightMouseButton = 0; break; case Common::EVENT_QUIT: // TODO - salir_al_dos(0); - exit(0); + endChapter(); + _system->quit(); break; default: break; @@ -1402,3200 +709,289 @@ void DrasculaEngine::update_events() { } } -void DrasculaEngine::elige_verbo(int verbo) { - int c = 171; - - if (menu_scr == 1) - c = 0; - if (num_ejec == 5) { - if (lleva_objeto == 1 && objeto_que_lleva != 16) - suma_objeto(objeto_que_lleva); - } else { - if (lleva_objeto == 1) - suma_objeto(objeto_que_lleva); - } - - copyBackground(ANCHOBJ * verbo, c, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3); - - lleva_objeto = 1; - objeto_que_lleva = verbo; -} - -void DrasculaEngine::mesa() { - int nivel_master, nivel_voc, nivel_cd; - - copyRect(1, 56, 73, 63, 177, 97, dir_mesa, dir_zona_pantalla); - updateScreen(73, 63, 73, 63, 177, 97, dir_zona_pantalla); - - for (;;) { - nivel_master = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4); - nivel_voc = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4); - nivel_cd = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4); - - updateRoom(); - - copyRect(1, 56, 73, 63, 177, 97, dir_mesa, dir_zona_pantalla); - - copyBackground(183, 56, 82, nivel_master, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4), dir_mesa, dir_zona_pantalla); - copyBackground(183, 56, 138, nivel_voc, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4), dir_mesa, dir_zona_pantalla); - copyBackground(183, 56, 194, nivel_cd, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4), dir_mesa, dir_zona_pantalla); - - cursor_mesa(); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - MirarRaton(); - - if (boton_dch == 1) { - delay(100); - break; - } - if (boton_izq == 1) { - delay(100); - if (x_raton > 80 && x_raton < 121) { - int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16; - if (y_raton < nivel_master && vol < 15) - vol++; - if (y_raton > nivel_master && vol > 0) - vol--; - _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol * 16); - } - - if (x_raton > 136 && x_raton < 178) { - int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16; - if (y_raton < nivel_voc && vol < 15) - vol++; - if (y_raton > nivel_voc && vol > 0) - vol--; - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol * 16); - } - - if (x_raton > 192 && x_raton < 233) { - int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16; - if (y_raton < nivel_cd && vol < 15) - vol++; - if (y_raton > nivel_cd && vol > 0) - vol--; - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol * 16); - } - } - - } - - espera_soltar(); -} - -bool DrasculaEngine::saves() { - char nombres[10][23]; - char fichero[13]; - int n, n2, num_sav = 0, y = 27; - Common::InSaveFile *sav; - - clearRoom(); - - if (!(sav = _saveFileMan->openForLoading("saves.epa"))) { - Common::OutSaveFile *epa; - if (!(epa = _saveFileMan->openForSaving("saves.epa"))) - error("Can't open saves.epa file."); - for (n = 0; n < NUM_SAVES; n++) - epa->writeString("*\n"); - epa->finalize(); - delete epa; - if (!(sav = _saveFileMan->openForLoading("saves.epa"))) { - error("Can't open saves.epa file."); - } - } - for (n = 0; n < NUM_SAVES; n++) - sav->readLine(nombres[n], 23); - delete sav; - - loadPic("savescr.alg"); - decompressPic(dir_dibujo1, MEDIA); - - color_abc(VERDE_CLARO); - - for (;;) { - y = 27; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - for (n = 0; n < NUM_SAVES; n++) { - print_abc(nombres[n], 116, y); - y = y + 9; - } - print_abc(select, 117, 15); - cursor_mesa(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - y = 27; - - MirarRaton(); - - if (boton_izq == 1) { - delay(100); - for (n = 0; n < NUM_SAVES; n++) { - if (x_raton > 115 && y_raton > y + (9 * n) && x_raton < 115 + 175 && y_raton < y + 10 + (9 * n)) { - strcpy(select, nombres[n]); - - if (strcmp(select, "*")) - hay_seleccion = 1; - else { - introduce_nombre(); - strcpy(nombres[n], select); - if (hay_seleccion == 1) { - sprintf(fichero, "gsave%02d", n + 1); - para_grabar(fichero); - Common::OutSaveFile *tsav; - if (!(tsav = _saveFileMan->openForSaving("saves.epa"))) { - error("Can't open saves.epa file."); - } - for (n = 0; n < NUM_SAVES; n++) { - tsav->writeString(nombres[n]); - tsav->writeString("\n"); - } - tsav->finalize(); - delete tsav; - } - } - - print_abc(select, 117, 15); - y = 27; - for (n2 = 0; n2 < NUM_SAVES; n2++) { - print_abc(nombres[n2], 116, y); - y = y + 9; - } - if (hay_seleccion == 1) { - sprintf(fichero, "gsave%02d", n + 1); - } - num_sav = n; - } - } - - if (x_raton > 117 && y_raton > 15 && x_raton < 295 && y_raton < 24 && hay_seleccion == 1) { - introduce_nombre(); - strcpy(nombres[num_sav], select); - print_abc(select, 117, 15); - y = 27; - for (n2 = 0; n2 < NUM_SAVES; n2++) { - print_abc(nombres[n2], 116, y); - y = y + 9; - } - } - - if (x_raton > 125 && y_raton > 123 && x_raton < 199 && y_raton < 149 && hay_seleccion == 1) { - if (!para_cargar(fichero)) - return false; - break; - } else if (x_raton > 208 && y_raton > 123 && x_raton < 282 && y_raton < 149 && hay_seleccion == 1) { - para_grabar(fichero); - Common::OutSaveFile *tsav; - if (!(tsav = _saveFileMan->openForSaving("saves.epa"))) { - error("Can't open saves.epa file."); - } - for (n = 0; n < NUM_SAVES; n++) { - tsav->writeString(nombres[n]); - tsav->writeString("\n"); - } - tsav->finalize(); - delete tsav; - } else if (x_raton > 168 && y_raton > 154 && x_raton < 242 && y_raton < 180) - break; - else if (hay_seleccion == 0) { - print_abc("elige una partida", 117, 15); - } - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - delay(400); - } - y = 26; - } - - clearRoom(); - loadPic(num_room); - decompressPic(dir_dibujo1, MEDIA); - buffer_teclado(); - hay_seleccion = 0; - - return true; -} - -void DrasculaEngine::print_abc(const char *dicho, int x_pantalla, int y_pantalla) { - int pos_texto[8]; - int y_de_letra = 0, x_de_letra = 0, h, longitud; - longitud = strlen(dicho); - - for (h = 0; h < longitud; h++) { - y_de_letra = Y_ABC; - int c = toupper(dicho[h]); - if (c == 'A') - x_de_letra = X_A; - else if (c == 'B') - x_de_letra = X_B; - else if (c == 'C') - x_de_letra = X_C; - else if (c == 'D') - x_de_letra = X_D; - else if (c == 'E') - x_de_letra = X_E; - else if (c == 'F') - x_de_letra = X_F; - else if (c == 'G') - x_de_letra = X_G; - else if (c == 'H') - x_de_letra = X_H; - else if (c == 'I') - x_de_letra = X_I; - else if (c == 'J') - x_de_letra = X_J; - else if (c == 'K') - x_de_letra = X_K; - else if (c == 'L') - x_de_letra = X_L; - else if (c == 'M') - x_de_letra = X_M; - else if (c == 'N') - x_de_letra = X_N; - else if (c == 'O') - x_de_letra = X_O; - else if (c == 'P') - x_de_letra = X_P; - else if (c == 'Q') - x_de_letra = X_Q; - else if (c == 'R') - x_de_letra = X_R; - else if (c == 'S') - x_de_letra = X_S; - else if (c == 'T') - x_de_letra = X_T; - else if (c == 'U') - x_de_letra = X_U; - else if (c == 'V') - x_de_letra = X_V; - else if (c == 'W') - x_de_letra = X_W; - else if (c == 'X') - x_de_letra = X_X; - else if (c == 'Y') - x_de_letra = X_Y; - else if (c == 'Z') - x_de_letra = X_Z; - else if (c == 0xa7 || c == ' ') - x_de_letra = ESPACIO; - else { - y_de_letra = Y_SIGNOS; - if (c == '.') - x_de_letra = X_PUNTO; - else if (c == ',') - x_de_letra = X_COMA; - else if (c == '-') - x_de_letra = X_GUION; - else if (c == '?') - x_de_letra = X_CIERRA_INTERROGACION; - else if (c == 0xa8) - x_de_letra = X_ABRE_INTERROGACION; -// else if (c == '\'') // FIXME -// x_de_letra = ESPACIO; // space for now - else if (c == '"') - x_de_letra = X_COMILLAS; - else if (c == '!') - x_de_letra = X_CIERRA_EXCLAMACION; - else if (c == 0xad) - x_de_letra = X_ABRE_EXCLAMACION; - else if (c == ';') - x_de_letra = X_PUNTO_Y_COMA; - else if (c == '>') - x_de_letra = X_MAYOR_QUE; - else if (c == '<') - x_de_letra = X_MENOR_QUE; - else if (c == '$') - x_de_letra = X_DOLAR; - else if (c == '%') - x_de_letra = X_POR_CIENTO; - else if (c == ':') - x_de_letra = X_DOS_PUNTOS; - else if (c == '&') - x_de_letra = X_AND; - else if (c == '/') - x_de_letra = X_BARRA; - else if (c == '(') - x_de_letra = X_ABRE_PARENTESIS; - else if (c == ')') - x_de_letra = X_CIERRA_PARENTESIS; - else if (c == '*') - x_de_letra = X_ASTERISCO; - else if (c == '+') - x_de_letra = X_MAS; - else if (c == '1') - x_de_letra = X_N1; - else if (c == '2') - x_de_letra = X_N2; - else if (c == '3') - x_de_letra = X_N3; - else if (c == '4') - x_de_letra = X_N4; - else if (c == '5') - x_de_letra = X_N5; - else if (c == '6') - x_de_letra = X_N6; - else if (c == '7') - x_de_letra = X_N7; - else if (c == '8') - x_de_letra = X_N8; - else if (c == '9') - x_de_letra = X_N9; - else if (c == '0') - x_de_letra = X_N0; - } - - pos_texto[0] = x_de_letra; - pos_texto[1] = y_de_letra; - pos_texto[2] = x_pantalla; - pos_texto[3] = y_pantalla; - pos_texto[4] = ANCHO_LETRAS; - pos_texto[5] = ALTO_LETRAS; - - copyRectClip(pos_texto, dir_texto, dir_zona_pantalla); - - x_pantalla = x_pantalla + ANCHO_LETRAS; - if (x_pantalla > 317) { - x_pantalla = 0; - y_pantalla = y_pantalla + ALTO_LETRAS + 2; - } - } -} - void DrasculaEngine::delay(int ms) { _system->delayMillis(ms * 2); // originaly was 1 } -bool DrasculaEngine::confirma_salir() { - byte key; - - color_abc(ROJO); - updateRoom(); - centra_texto(_textsys[_lang][1], 160, 87); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - delay(100); - for (;;) { - key = getscan(); - if (key != 0) - break; - } - - if (key == Common::KEYCODE_ESCAPE) { - stopmusic(); - return false; - } - - return true; +void DrasculaEngine::pause(int duration) { + _system->delayMillis(duration * 30); // was originaly 2 } -void DrasculaEngine::salva_pantallas() { - int xr, yr; - - // FIXME: that part (*.ghost) need RE from efecto.lib file for some gfx special effect - // for now ignore - return; - - clearRoom(); - - loadPic("sv.alg"); - decompressPic(dir_dibujo1, MEDIA); - //TODO inicio_ghost(); - //TODO carga_ghost(); - - MirarRaton(); - xr = x_raton; - yr = y_raton; - - for (;;) { - //TODO efecto(dir_dibujo1); - MirarRaton(); - if (boton_dch == 1 || boton_izq == 1) - break; - if (x_raton != xr) - break; - if (y_raton != yr) - break; - } - //TODO fin_ghost(); - loadPic(num_room); - decompressPic(dir_dibujo1, MEDIA); -} - -void DrasculaEngine::fliplay(const char *filefli, int vel) { - OpenSSN(filefli, vel); - while (PlayFrameSSN() && (!term_int)) { - if (getscan() == Common::KEYCODE_ESCAPE) - term_int = 1; - } - EndSSN(); -} - -void DrasculaEngine::FundeDelNegro(int VelocidadDeFundido) { - char fundido; - unsigned int color, componente; - - DacPalette256 palFundido; - - for (fundido = 0; fundido < 64; fundido++) { - for (color = 0; color < 256; color++) { - for (componente = 0; componente < 3; componente++) { - palFundido[color][componente] = LimitaVGA(palJuego[color][componente] - 63 + fundido); - } - } - pause(VelocidadDeFundido); - - setvgapalette256((byte *)&palFundido); - } -} - -void DrasculaEngine::color_abc(int cl) { - _color = cl; - - if (cl == 0) { - palJuego[254][0] = 0; - palJuego[254][1] = 0; - palJuego[254][2] = 0; - } else if (cl == 1) { - palJuego[254][0] = 0x10; - palJuego[254][1] = 0x3E; - palJuego[254][2] = 0x28; - } else if (cl == 3) { - palJuego[254][0] = 0x16; - palJuego[254][1] = 0x3F; - palJuego[254][2] = 0x16; - } else if (cl == 4) { - palJuego[254][0] = 0x9; - palJuego[254][1] = 0x3F; - palJuego[254][2] = 0x12; - } else if (cl == 5) { - palJuego[254][0] = 0x3F; - palJuego[254][1] = 0x3F; - palJuego[254][2] = 0x15; - } else if (cl == 7) { - palJuego[254][0] = 0x38; - palJuego[254][1] = 0; - palJuego[254][2] = 0; - } else if (cl == 8) { - palJuego[254][0] = 0x3F; - palJuego[254][1] = 0x27; - palJuego[254][2] = 0x0B; - } else if (cl == 9) { - palJuego[254][0] = 0x2A; - palJuego[254][1] = 0; - palJuego[254][2] = 0x2A; - } else if (cl == 10) { - palJuego[254][0] = 0x30; - palJuego[254][1] = 0x30; - palJuego[254][2] = 0x30; - } else if (cl == 11) { - palJuego[254][0] = 98; - palJuego[254][1] = 91; - palJuego[254][2] = 100; - }; - - setvgapalette256((byte *)&palJuego); -} - -char DrasculaEngine::LimitaVGA(char valor) { - return (valor & 0x3F) * (valor > 0); +int DrasculaEngine::getTime() { + return _system->getMillis() / 20; // originaly was 1 } -void DrasculaEngine::centra_texto(const char *mensaje, int x_texto, int y_texto) { - char bb[200], m2[200], m1[200], mb[10][50]; - char m3[200]; - int h, fil, x_texto3, x_texto2, x_texto1, conta_f = 0, ya = 0; - - strcpy(m1, " "); - strcpy(m2, " "); - strcpy(m3, " "); - strcpy(bb, " "); - - for (h = 0; h < 10; h++) - strcpy(mb[h], " "); - - if (x_texto > 160) - ya = 1; - - strcpy(m1, mensaje); - if (x_texto < 60) - x_texto = 60; - if (x_texto > 255) - x_texto = 255; - - x_texto1 = x_texto; - - if (ya == 1) - x_texto1 = 315 - x_texto; - - x_texto2 = (strlen(m1) / 2) * ANCHO_LETRAS; - -tut: - strcpy(bb, m1); - scumm_strrev(bb); - - if (x_texto1 < x_texto2) { - strcpy(m3, strrchr(m1, ' ')); - strcpy(m1, strstr(bb, " ")); - scumm_strrev(m1); - m1[strlen(m1) - 1] = '\0'; - strcat(m3, m2); - strcpy(m2, m3); - }; - - x_texto2 = (strlen(m1) / 2) * ANCHO_LETRAS; - if (x_texto1 < x_texto2) - goto tut; - strcpy(mb[conta_f], m1); - - if (!strcmp(m2, "")) - goto imprimir; - scumm_strrev(m2); - m2[strlen(m2) - 1] = '\0'; - scumm_strrev(m2); - strcpy(m1, m2); - strcpy(m2, ""); - conta_f++; - - goto tut; - -imprimir: - - fil = y_texto - (((conta_f + 3) * ALTO_LETRAS)); - - for (h = 0; h < conta_f + 1; h++) { - x_texto3 = strlen(mb[h]) / 2; - print_abc(mb[h], ((x_texto) - x_texto3 * ANCHO_LETRAS) - 1, fil); - fil = fil + ALTO_LETRAS + 2; - } -} +void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int width, int height, int factor, byte *dir_inicio, byte *dir_fin) { + float totalX, totalY; + int n, m; + float pixelX, pixelY; + int pixelPos[6]; -void DrasculaEngine::comienza_sound(const char *fichero) { - if (hay_sb == 1) { - sku = new Common::File; - sku->open(fichero); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); -} + newWidth = (width * factor) / 100; + newHeight = (height * factor) / 100; -void DrasculaEngine::anima(const char *animation, int FPS) { - Common::File FileIn; - unsigned j; - int NFrames = 1; - int cnt = 2; + totalX = width / newWidth; + totalY = height / newHeight; - AuxBuffLast = (byte *)malloc(65000); - AuxBuffDes = (byte *)malloc(65000); + pixelX = xx1; + pixelY = yy1; - FileIn.open(animation); + for (n = 0; n < newHeight; n++) { + for (m = 0; m < newWidth; m++) { + pixelPos[0] = (int)pixelX; + pixelPos[1] = (int)pixelY; + pixelPos[2] = xx2 + m; + pixelPos[3] = yy2 + n; + pixelPos[4] = 1; + pixelPos[5] = 1; - if (!FileIn.isOpen()) { - error("No encuentro un fichero de animation."); - } + copyRectClip(pixelPos, dir_inicio, dir_fin); - FileIn.read(&NFrames, sizeof(NFrames)); - FileIn.read(&Leng, sizeof(Leng)); - AuxBuffOrg = (byte *)malloc(Leng); - FileIn.read(AuxBuffOrg, Leng); - FileIn.read(cPal, 768); - carga_pcx(AuxBuffOrg); - free(AuxBuffOrg); - memcpy(VGA, AuxBuffDes, 64000); - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - _system->updateScreen(); - set_dac(cPal); - memcpy(AuxBuffLast, AuxBuffDes, 64000); - WaitForNext(FPS); - while (cnt < NFrames) { - FileIn.read(&Leng, sizeof(Leng)); - AuxBuffOrg = (byte *)malloc(Leng); - FileIn.read(AuxBuffOrg, Leng); - FileIn.read(cPal, 768); - carga_pcx(AuxBuffOrg); - free(AuxBuffOrg); - for (j = 0;j < 64000; j++) { - VGA[j] = AuxBuffLast[j] = AuxBuffDes[j] ^ AuxBuffLast[j]; + pixelX += totalX; } - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - _system->updateScreen(); - WaitForNext(FPS); - cnt++; - byte key = getscan(); - if (key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - break; - } - free(AuxBuffLast); - free(AuxBuffDes); - FileIn.close(); -} - -void DrasculaEngine::animafin_sound_corte() { - if (hay_sb == 1) { - ctvd_stop(); - delete sku; - sku = NULL; - ctvd_terminate(); + pixelX = xx1; + pixelY += totalY; } } -void DrasculaEngine::FundeAlNegro(int VelocidadDeFundido) { - char fundido; - unsigned int color, componente; - - DacPalette256 palFundido; - - for (fundido = 63; fundido >= 0; fundido--) { - for (color = 0; color < 256; color++) { - for (componente = 0; componente < 3; componente++) { - palFundido[color][componente] = LimitaVGA(palJuego[color][componente] - 63 + fundido); - } - } - pause(VelocidadDeFundido); - - setvgapalette256((byte *)&palFundido); - } -} - -void DrasculaEngine::pause(int cuanto) { - _system->delayMillis(cuanto * 30); // was originaly 2 -} - -void DrasculaEngine::pon_igor() { - int pos_igor[6]; - - pos_igor[0] = 1; - if (num_ejec == 4) { - pos_igor[1] = 138; - } else { - if (sentido_igor == 3) - pos_igor[1] = 138; - else if (sentido_igor == 1) - pos_igor[1] = 76; - } - pos_igor[2] = x_igor; - pos_igor[3] = y_igor; - pos_igor[4] = 54; - pos_igor[5] = 61; - - copyRectClip(pos_igor, dir_hare_frente, dir_zona_pantalla); -} - -void DrasculaEngine::pon_dr() { - int pos_dr[6]; - - if (sentido_dr == 1) - pos_dr[0] = 47; - else if (sentido_dr == 0) - pos_dr[0] = 1; - else if (sentido_dr == 3 && num_ejec == 1) - pos_dr[0] = 93; - pos_dr[1] = 122; - pos_dr[2] = x_dr; - pos_dr[3] = y_dr; - pos_dr[4] = 45; - pos_dr[5] = 77; - - if (num_ejec == 6) - copyRectClip(pos_dr, dir_dibujo2, dir_zona_pantalla); - else - copyRectClip(pos_dr, dir_hare_fondo, dir_zona_pantalla); -} - -void DrasculaEngine::pon_bj() { - int pos_bj[6]; - - if (sentido_bj == 3) - pos_bj[0] = 10; - else if (sentido_bj == 0) - pos_bj[0] = 37; - pos_bj[1] = 99; - pos_bj[2] = x_bj; - pos_bj[3] = y_bj; - pos_bj[4] = 26; - pos_bj[5] = 76; - - copyRectClip(pos_bj, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::hipo(int contador) { - int y = 0, sentido = 0; - if (num_ejec == 3) +void DrasculaEngine::hipo_sin_nadie(int counter){ + int y = 0, trackCharacter = 0; + if (currentChapter == 3) y = -1; -comienza: - contador--; - - updateRoom(); - if (num_ejec == 3) - updateScreen(0, 0, 0, y, 320, 200, dir_zona_pantalla); - else - updateScreen(0, 1, 0, y, 320, 198, dir_zona_pantalla); - - if (sentido == 0) - y++; - else - y--; - - if (num_ejec == 3) { - if (y == 1) - sentido = 1; - if (y == -1) - sentido = 0; - } else { - if (y == 2) - sentido = 1; - if (y == 0) - sentido = 0; - } - if (contador > 0) - goto comienza; - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::fin_sound() { - delay(1); - - if (hay_sb == 1) { - while (LookForFree() != 0); - delete sku; - sku = NULL; - } -} - -void DrasculaEngine::playmusic(int p) { - AudioCD.stop(); - AudioCD.play(p - 1, 1, 0, 0); -} - -void DrasculaEngine::stopmusic() { - AudioCD.stop(); -} + do { + counter--; -int DrasculaEngine::music_status() { - return AudioCD.isPlaying(); -} - -void DrasculaEngine::updateRoom() { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateRefresh_pre(); - if (num_ejec == 3) { - if (flags[0] == 0) - pon_hare(); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + if (currentChapter == 3) + updateScreen(0, 0, 0, y, 320, 200, screenSurface); else - copyRect(113, 54, hare_x - 20, hare_y - 1, 77, 89, dir_dibujo3, dir_zona_pantalla); - } else { - pon_hare(); - } - updateRefresh(); -} - -bool DrasculaEngine::carga_partida(const char *nom_game) { - int l, n_ejec2; - Common::InSaveFile *sav; - - if (!(sav = _saveFileMan->openForLoading(nom_game))) { - error("missing savegame file"); - } - - n_ejec2 = sav->readSint32LE(); - if (n_ejec2 != num_ejec) { - strcpy(nom_partida, nom_game); - num_ejec = n_ejec2 - 1; - hay_que_load = 1; - return false; - } - sav->read(datos_actuales, 20); - hare_x = sav->readSint32LE(); - hare_y = sav->readSint32LE(); - sentido_hare = sav->readSint32LE(); - - for (l = 1; l < 43; l++) { - objetos_que_tengo[l] = sav->readSint32LE(); - } - - for (l = 0; l < NUM_BANDERAS; l++) { - flags[l] = sav->readSint32LE(); - } - - lleva_objeto = sav->readSint32LE(); - objeto_que_lleva = sav->readSint32LE(); - hay_que_load = 0; - - return true; -} - -void DrasculaEngine::puertas_cerradas(int l) { - if (num_ejec == 1 || num_ejec == 3 || num_ejec == 5 || num_ejec == 6) - return; - else if (num_ejec == 2) { - if (num_obj[l] == 138 && flags[0] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 138 && flags[0] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 136 && flags[8] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 136 && flags[8] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 156 && flags[16] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 156 && flags[16] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 163 && flags[17] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 163 && flags[17] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 177 && flags[15] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 177 && flags[15] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 175 && flags[40] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 175 && flags[40] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 173 && flags[36] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 173 && flags[36] == 1) - espuerta[l] = 1; - } else if (num_ejec == 4) { - if (num_obj[l] == 101 && flags[0] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 101 && flags[0] == 1 && flags[28] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 103 && flags[0] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 103 && flags[0] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 104 && flags[1] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 104 && flags[1] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 105 && flags[1] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 105 && flags[1] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 106 && flags[2] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 106 && flags[2] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 107 && flags[2] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 107 && flags[2] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 110 && flags[6] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 110 && flags[6] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 114 && flags[4] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 114 && flags[4] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 115 && flags[4] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 115 && flags[4] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 116 && flags[5] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 116 && flags[5] == 1 && flags[23] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 117 && flags[5] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 117 && flags[5] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 120 && flags[8] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 120 && flags[8] == 1) - espuerta[l] = 1; - else if (num_obj[l] == 122 && flags[7] == 0) - espuerta[l] = 0; - else if (num_obj[l] == 122 && flags[7] == 1) - espuerta[l] = 1; - } -} - -void DrasculaEngine::color_hare() { - int color, componente; - - for (color = 235; color < 253; color++) { - for (componente = 0; componente < 3; componente++) { - palJuego[color][componente] = palHare[color][componente]; - } - } - ActualizaPaleta(); -} - -void DrasculaEngine::funde_hare(int oscuridad) { - char fundido; - unsigned int color, componente; - - for (fundido = oscuridad; fundido >= 0; fundido--) { - for (color = 235; color < 253; color++) { - for (componente = 0; componente < 3; componente++) - palJuego[color][componente] = LimitaVGA(palJuego[color][componente] - 8 + fundido); - } - } - - ActualizaPaleta(); -} - -void DrasculaEngine::paleta_hare_claro() { - int color, componente; - - for (color = 235; color < 253; color++) { - for (componente = 0; componente < 3; componente++) - palHareClaro[color][componente] = palJuego[color][componente]; - } -} + updateScreen(0, 1, 0, y, 320, 198, screenSurface); -void DrasculaEngine::paleta_hare_oscuro() { - int color, componente; - - for (color = 235; color < 253; color++) { - for (componente = 0; componente < 3; componente++) - palHareOscuro[color][componente] = palJuego[color][componente]; - } -} - -void DrasculaEngine::hare_claro() { - int color, componente; - - for (color = 235; color < 253; color++) { - for (componente = 0; componente < 3; componente++) - palJuego[color][componente] = palHareClaro[color][componente]; - } - - ActualizaPaleta(); -} - -void DrasculaEngine::empieza_andar() { - hare_se_mueve = 1; - - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - - if (num_ejec == 2) { - if ((sitio_x < hare_x) && (sitio_y <= (hare_y + alto_hare))) - cuadrante_1(); - else if ((sitio_x < hare_x) && (sitio_y > (hare_y + alto_hare))) - cuadrante_3(); - else if ((sitio_x > hare_x + ancho_hare) && (sitio_y <= (hare_y + alto_hare))) - cuadrante_2(); - else if ((sitio_x > hare_x + ancho_hare) && (sitio_y > (hare_y + alto_hare))) - cuadrante_4(); - else if (sitio_y < hare_y + alto_hare) - anda_parriba(); - else if (sitio_y > hare_y + alto_hare) - anda_pabajo(); - } else { - if ((sitio_x < hare_x + ancho_hare / 2 ) && (sitio_y <= (hare_y + alto_hare))) - cuadrante_1(); - else if ((sitio_x < hare_x + ancho_hare / 2) && (sitio_y > (hare_y + alto_hare))) - cuadrante_3(); - else if ((sitio_x > hare_x + ancho_hare / 2) && (sitio_y <= (hare_y + alto_hare))) - cuadrante_2(); - else if ((sitio_x > hare_x + ancho_hare / 2) && (sitio_y > (hare_y + alto_hare))) - cuadrante_4(); + if (trackCharacter == 0) + y++; else - hare_se_mueve = 0; - } - conta_vez = vez(); -} - -void DrasculaEngine::pon_hare() { - int pos_hare[6]; - int r; - - if (hare_se_mueve == 1 && paso_x == PASO_HARE_X) { - for (r = 0; r < paso_x; r++) { - if (num_ejec != 2) { - if (sentido_hare == 0 && sitio_x - r == hare_x + ancho_hare / 2) { - hare_se_mueve = 0; - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - } - if (sentido_hare == 1 && sitio_x + r == hare_x + ancho_hare / 2) { - hare_se_mueve = 0; - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - hare_x = sitio_x - ancho_hare / 2; - hare_y = sitio_y - alto_hare; - } - } else if (num_ejec == 2) { - if (sentido_hare == 0 && sitio_x - r == hare_x) { - hare_se_mueve = 0; - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - } - if (sentido_hare == 1 && sitio_x + r == hare_x + ancho_hare) { - hare_se_mueve = 0; - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - hare_x = sitio_x - ancho_hare + 4; - hare_y = sitio_y - alto_hare; - } - } - } - } - if (hare_se_mueve == 1 && paso_y == PASO_HARE_Y) { - for (r = 0; r < paso_y; r++) { - if (sentido_hare == 2 && sitio_y - r == hare_y + alto_hare) { - hare_se_mueve = 0; - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - } - if (sentido_hare == 3 && sitio_y + r == hare_y + alto_hare) { - hare_se_mueve = 0; - paso_x = PASO_HARE_X; - paso_y = PASO_HARE_Y; - } - } - } - - if (num_ejec == 1 || num_ejec == 4 || num_ejec == 5 || num_ejec == 6) { - if (hare_se_ve == 0) - goto no_vuelco; - } - - if (hare_se_mueve == 0) { - pos_hare[0] = 0; - pos_hare[1] = DIF_MASK_HARE; - pos_hare[2] = hare_x; - pos_hare[3] = hare_y; - if (num_ejec == 2) { - pos_hare[4] = ancho_hare; - pos_hare[5] = alto_hare; - } else { - pos_hare[4] = ANCHO_PERSONAJE; - pos_hare[5] = ALTO_PERSONAJE; - } - - if (sentido_hare == 0) { - pos_hare[1] = 0; - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - } else if (sentido_hare == 1) { - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - } else if (sentido_hare == 2) { - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_fondo, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_fondo, dir_zona_pantalla); - } else { - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_frente, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_frente, dir_zona_pantalla); - } - } else if (hare_se_mueve == 1) { - pos_hare[0] = frame_x[num_frame]; - pos_hare[1] = frame_y + DIF_MASK_HARE; - pos_hare[2] = hare_x; - pos_hare[3] = hare_y; - if (num_ejec == 2) { - pos_hare[4] = ancho_hare; - pos_hare[5] = alto_hare; - } else { - pos_hare[4] = ANCHO_PERSONAJE; - pos_hare[5] = ALTO_PERSONAJE; - } - if (sentido_hare == 0) { - pos_hare[1] = 0; - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - } else if (sentido_hare == 1) { - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - } else if (sentido_hare == 2) { - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_fondo, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_fondo, dir_zona_pantalla); - } else { - if (num_ejec == 2) - copyRectClip(pos_hare, dir_hare_frente, dir_zona_pantalla); - else - reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5], - factor_red[hare_y + alto_hare], dir_hare_frente, dir_zona_pantalla); - } - -no_vuelco: - aumenta_num_frame(); - } -} - -void DrasculaEngine::menu_sin_volcar() { - int h, n, x; - char texto_icono[13]; - - x = sobre_que_objeto(); - strcpy(texto_icono, nombre_icono[x]); - - for (n = 1; n < 43; n++) { - h = objetos_que_tengo[n]; - - if (h != 0) { - if (num_ejec == 6) - copyBackground(x_pol[n], y_pol[n], x_obj[n], y_obj[n], - ANCHOBJ, ALTOBJ, dir_mesa, dir_zona_pantalla); - else - copyBackground(x_pol[n], y_pol[n], x_obj[n], y_obj[n], - ANCHOBJ, ALTOBJ, dir_hare_frente, dir_zona_pantalla); - } - copyRect(x1d_menu[h], y1d_menu[h], x_obj[n], y_obj[n], - ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_zona_pantalla); - } - - if (x < 7) - print_abc(texto_icono, x_obj[x] - 2, y_obj[x] - 7); -} - -void DrasculaEngine::barra_menu() { - int n, sobre_verbo = 1; - - for (n = 0; n < 7; n++) { - if (x_raton > x_barra[n] && x_raton < x_barra[n + 1]) - sobre_verbo = 0; - copyRect(ANCHOBJ * n, ALTOBJ * sobre_verbo, x_barra[n], 2, - ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_zona_pantalla); - sobre_verbo = 1; - } -} - -void DrasculaEngine::saca_objeto() { - int h = 0, n; - - updateRoom(); - - for (n = 1; n < 43; n++){ - if (sobre_que_objeto() == n) { - h = objetos_que_tengo[n]; - objetos_que_tengo[n] = 0; - if (h != 0) - lleva_objeto = 1; - } - } - - espera_soltar(); - - if (lleva_objeto == 1) - elige_objeto(h); -} - -bool DrasculaEngine::sal_de_la_habitacion(int l) { - char salgo[13]; - - if (num_ejec == 1) { - if (num_obj[l] == 105 && flags[0] == 0) - talk(_text[_lang][442], "442.als"); - else { - puertas_cerradas(l); - if (espuerta[l] != 0) { - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - sentido_hare = sentidobj[l]; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - hare_se_mueve = 0; - sentido_hare = sentido_alkeva[l]; - obj_saliendo = alapuertakeva[l]; - rompo = 1; - musica_antes = musica_room; - - if (num_obj[l] == 105) { - animation_2_1(); - return true; - } - clearRoom(); - strcpy(salgo, alapantallakeva[l]); - strcat(salgo, ".ald"); - hare_x = -1; - carga_escoba(salgo); - } - } - } else if (num_ejec == 2) { - puertas_cerradas(l); - if (espuerta[l] != 0) { - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - hare_se_mueve = 0; - sentido_hare = sentido_alkeva[l]; - obj_saliendo = alapuertakeva[l]; - rompo = 1; - musica_antes = musica_room; - if (num_obj[l] == 136) - animation_2_2(); - if (num_obj[l] == 124) - animation_3_2(); - if (num_obj[l] == 173) { - animation_35_2(); - return true; - } if (num_obj[l] == 146 && flags[39] == 1) { - flags[5] = 1; - flags[11] = 1; - } - if (num_obj[l] == 176 && flags[29] == 1) { - flags[29] = 0; - resta_objeto(23); - suma_objeto(11); - } - clearRoom(); - delete ald; - ald = NULL; - strcpy(salgo, alapantallakeva[l]); - strcat(salgo, ".ald"); - hare_x =- 1; - carga_escoba(salgo); - } - } else if (num_ejec == 3) { - puertas_cerradas(l); - if (espuerta[l] != 0 && visible[l] == 1) { - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - sentido_hare = sentidobj[l]; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - hare_se_mueve = 0; - sentido_hare = sentido_alkeva[l]; - obj_saliendo = alapuertakeva[l]; - rompo = 1; - musica_antes = musica_room; - clearRoom(); - strcpy(salgo, alapantallakeva[l]); - strcat(salgo, ".ald"); - hare_x =- 1; - carga_escoba(salgo); - } - } else if (num_ejec == 4) { - puertas_cerradas(l); - if (espuerta[l] != 0) { - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - sentido_hare = sentidobj[l]; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - hare_se_mueve = 0; - sentido_hare = sentido_alkeva[l]; - obj_saliendo = alapuertakeva[l]; - rompo = 1; - musica_antes = musica_room; - - if (num_obj[l] == 108) - lleva_al_hare(171, 78); - clearRoom(); - strcpy(salgo, alapantallakeva[l]); - strcat(salgo, ".ald"); - hare_x = -1; - carga_escoba(salgo); - } - } else if (num_ejec == 5) { - puertas_cerradas(l); - if (espuerta[l] != 0 && visible[l] == 1) { - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - sentido_hare = sentidobj[l]; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - hare_se_mueve = 0; - sentido_hare = sentido_alkeva[l]; - obj_saliendo = alapuertakeva[l]; - rompo = 1; - musica_antes = musica_room; - hare_se_ve = 1; - clearRoom(); - strcpy(salgo, alapantallakeva[l]); - strcat(salgo, ".ald"); - hare_x = -1; - carga_escoba(salgo); - } - } else if (num_ejec == 6) { - puertas_cerradas(l); - if (espuerta[l] != 0) { - lleva_al_hare(sitiobj_x[l], sitiobj_y[l]); - sentido_hare = sentidobj[l]; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - hare_se_mueve = 0; - sentido_hare = sentido_alkeva[l]; - obj_saliendo = alapuertakeva[l]; - rompo = 1; - musica_antes = musica_room; - clearRoom(); - strcpy(salgo, alapantallakeva[l]); - strcat(salgo, ".ald"); - hare_x = -1; - carga_escoba(salgo); - - if (obj_saliendo == 105) - animation_19_6(); - } - } - - return false; -} - -bool DrasculaEngine::coge_objeto() { - int h, n; - h = objeto_que_lleva; - comprueba_flags = 1; - - updateRoom(); - menu_sin_volcar(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - if (objeto_que_lleva < 7) - goto usando_verbos; - - for (n = 1; n < 43; n++) { - if (sobre_que_objeto() == n && objetos_que_tengo[n] == 0) { - objetos_que_tengo[n] = h; - lleva_objeto = 0; - comprueba_flags = 0; - } - } - -usando_verbos: - - if (comprueba_flags == 1) { - if (comprueba_banderas_menu()) - return true; - } - espera_soltar(); - if (lleva_objeto == 0) - sin_verbo(); - - return false; -} - -bool DrasculaEngine::banderas(int fl) { - hare_se_mueve = 0; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - hay_respuesta = 1; - - if (menu_scr == 1) { - if (num_ejec == 1) { - if (objeto_que_lleva == LOOK && fl == 28) - talk(_text[_lang][328], "328.als"); - } else if (num_ejec == 2) { - if ((objeto_que_lleva == LOOK && fl == 22 && flags[23] == 0) - || (objeto_que_lleva == OPEN && fl == 22 && flags[23] == 0)) { - talk(_text[_lang][164], "164.als"); - flags[23] = 1; - sin_verbo(); - suma_objeto(7); - suma_objeto(18); - } else if (objeto_que_lleva == LOOK && fl == 22 && flags[23] == 1) - talk(_text[_lang][307], "307.als"); - else if (objeto_que_lleva == LOOK && fl == 28) - talk(_text[_lang][328], "328.als"); - else if (objeto_que_lleva == LOOK && fl == 7) - talk(_text[_lang][143], "143.als"); - else if (objeto_que_lleva == TALK && fl == 7) - talk(_text[_lang][144], "144.als"); - else if (objeto_que_lleva == LOOK && fl == 8) - talk(_text[_lang][145], "145.als"); - else if (objeto_que_lleva == TALK && fl == 8) - talk(_text[_lang][146], "146.als"); - else if (objeto_que_lleva == LOOK && fl == 9) - talk(_text[_lang][147], "147.als"); - else if (objeto_que_lleva == TALK && fl == 9) - talk(_text[_lang][148], "148.als"); - else if (objeto_que_lleva == LOOK && fl == 10) - talk(_text[_lang][151], "151.als"); - else if (objeto_que_lleva == LOOK && fl == 11) - talk(_text[_lang][152], "152.als"); - else if (objeto_que_lleva == TALK && fl == 11) - talk(_text[_lang][153], "153.als"); - else if (objeto_que_lleva == LOOK && fl == 12) - talk(_text[_lang][154], "154.als"); - else if (objeto_que_lleva == LOOK && fl == 13) - talk(_text[_lang][155], "155.als"); - else if (objeto_que_lleva == LOOK && fl == 14) - talk(_text[_lang][157], "157.als"); - else if (objeto_que_lleva == LOOK && fl == 15) - talk(_text[_lang][58], "58.als"); - else if (objeto_que_lleva == LOOK && fl == 16) - talk(_text[_lang][158], "158.als"); - else if (objeto_que_lleva == LOOK && fl == 17) - talk(_text[_lang][159], "159.als"); - else if (objeto_que_lleva == LOOK && fl == 18) - talk(_text[_lang][160], "160.als"); - else if (objeto_que_lleva == LOOK && fl == 19) - talk(_text[_lang][161], "161.als"); - else if (objeto_que_lleva == LOOK && fl == 20) - talk(_text[_lang][162], "162.als"); - else if (objeto_que_lleva == LOOK && fl == 23) - talk(_text[_lang][152], "152.als"); - else - hay_respuesta = 0; - } else if (num_ejec == 3) { - if (objeto_que_lleva == LOOK && fl == 22) - talk(_text[_lang][307], "307.als"); - else if (objeto_que_lleva == LOOK && fl == 28) - talk(_text[_lang][328], "328.als"); - else if (objeto_que_lleva == LOOK && fl == 7) - talk(_text[_lang][143], "143.als"); - else if (objeto_que_lleva == TALK && fl == 7) - talk(_text[_lang][144], "144.als"); - else if (objeto_que_lleva == LOOK && fl == 8) - talk(_text[_lang][145], "145.als"); - else if (objeto_que_lleva == TALK && fl == 8) - talk(_text[_lang][146], "146.als"); - else if (objeto_que_lleva == LOOK && fl == 9) - talk(_text[_lang][147], "147.als"); - else if (objeto_que_lleva == TALK && fl == 9) - talk(_text[_lang][148], "148.als"); - else if (objeto_que_lleva == LOOK && fl == 10) - talk(_text[_lang][151], "151.als"); - else if (objeto_que_lleva == LOOK && fl == 11) - talk(_text[_lang][152], "152.als"); - else if (objeto_que_lleva == TALK && fl == 11) - talk(_text[_lang][153], "153.als"); - else if (objeto_que_lleva == LOOK && fl == 12) - talk(_text[_lang][154], "154.als"); - else if (objeto_que_lleva == LOOK && fl == 13) - talk(_text[_lang][155], "155.als"); - else if (objeto_que_lleva == LOOK && fl == 14) - talk(_text[_lang][157], "157.als"); - else if (objeto_que_lleva == LOOK && fl == 15) - talk(_text[_lang][58], "58.als"); - else if (objeto_que_lleva == LOOK && fl == 16) - talk(_text[_lang][158], "158.als"); - else if (objeto_que_lleva == LOOK && fl == 17) - talk(_text[_lang][159], "159.als"); - else if (objeto_que_lleva == LOOK && fl == 18) - talk(_text[_lang][160], "160.als"); - else if (objeto_que_lleva == LOOK && fl == 19) - talk(_text[_lang][161], "161.als"); - else if (objeto_que_lleva == LOOK && fl == 20) - talk(_text[_lang][162], "162.als"); - else if (objeto_que_lleva == LOOK && fl == 23) - talk(_text[_lang][152], "152.als"); - else - hay_respuesta = 0; - } else if (num_ejec == 4) { - if ((objeto_que_lleva == 18 && fl == 19) || (objeto_que_lleva == 19 && fl == 18)) { - sin_verbo(); - elige_objeto(21); - resta_objeto(18); - resta_objeto(19); - } else if ((objeto_que_lleva == 14 && fl == 19) || (objeto_que_lleva == 19 && fl == 14)) - talk(_text[_lang][484], "484.als"); - else if (objeto_que_lleva == LOOK && fl == 28) - talk(_text[_lang][328], "328.als"); - else if (objeto_que_lleva == LOOK && fl == 7) - talk(_text[_lang][478], "478.als"); - else if (objeto_que_lleva == LOOK && fl == 8) - talk(_text[_lang][480], "480.als"); - else if (objeto_que_lleva == LOOK && fl == 9) { - talk(_text[_lang][482], "482.als"); - talk(_text[_lang][483], "483.als"); - } else if (objeto_que_lleva == LOOK && fl == 10) - talk(_text[_lang][485], "485.als"); - else if (objeto_que_lleva == LOOK && fl == 11) - talk(_text[_lang][488], "488.als"); - else if (objeto_que_lleva == LOOK && fl == 12) - talk(_text[_lang][486], "486.als"); - else if (objeto_que_lleva == LOOK && fl == 13) - talk(_text[_lang][490], "490.als"); - else if (objeto_que_lleva == LOOK && fl == 14) - talk(_text[_lang][122], "122.als"); - else if (objeto_que_lleva == LOOK && fl == 15) - talk(_text[_lang][117], "117.als"); - else if (objeto_que_lleva == TALK && fl == 15) - talk(_text[_lang][118], "118.als"); - else if (objeto_que_lleva == OPEN && fl == 15) - talk(_text[_lang][119], "119.als"); - else if (objeto_que_lleva == LOOK && fl == 16) - talk(_text[_lang][491], "491.als"); - else if (objeto_que_lleva == LOOK && fl == 17) - talk(_text[_lang][478], "478.als"); - else if (objeto_que_lleva == LOOK && fl == 18) - talk(_text[_lang][493], "493.als"); - else if (objeto_que_lleva == LOOK && fl == 19) { - talk(_text[_lang][494], "494.als"); - talk(_text[_lang][495], "495.als"); - } else if (objeto_que_lleva == LOOK && fl == 20) - talk(_text[_lang][162], "162.als"); - else if (objeto_que_lleva == LOOK && fl == 21) - talk(_text[_lang][496], "496.als"); - else if (objeto_que_lleva == LOOK && fl == 22) - talk(_text[_lang][161], "161.als"); - else - hay_respuesta = 0; - } else if (num_ejec == 5) { - if (objeto_que_lleva == LOOK && fl == 28) - talk(_text[_lang][328], "328.als"); - else if (objeto_que_lleva == LOOK && fl == 7) - talk(_text[_lang][478],"478.als"); - else if (objeto_que_lleva == LOOK && fl == 8) - talk(_text[_lang][120], "120.als"); - else if (objeto_que_lleva == LOOK && fl == 9) { - talk(_text[_lang][482], "482.als"); - talk(_text[_lang][483], "483.als"); - } else if (objeto_que_lleva == LOOK && fl == 11) - talk(_text[_lang][488], "488.als"); - else if (objeto_que_lleva == LOOK && fl == 13) - talk(_text[_lang][490], "490.als"); - else if (objeto_que_lleva == LOOK && fl == 14) - talk(_text[_lang][121], "121.als"); - else if (objeto_que_lleva == LOOK && fl == 15) - talk(_text[_lang][117], "117.als"); - else if (objeto_que_lleva == TALK && fl == 15) - talk(_text[_lang][118], "118.als"); - else if (objeto_que_lleva == OPEN && fl == 15) - talk(_text[_lang][119], "119.als"); - else if (objeto_que_lleva == LOOK && fl == 17) - talk(_text[_lang][478], "478.als"); - else if (objeto_que_lleva == LOOK && fl == 20) - talk(_text[_lang][162], "162.als"); - else - hay_respuesta = 0; - } else if (num_ejec == 6) { - if (objeto_que_lleva == LOOK && fl == 28) - talk(_text[_lang][328], "328.als"); - else if (objeto_que_lleva == LOOK && fl == 9) { - talk(_text[_lang][482], "482.als"); - talk(_text[_lang][483], "483.als"); - } else if (objeto_que_lleva == LOOK && fl == 20) - talk(_text[_lang][123], "123.als"); - else if (objeto_que_lleva == LOOK && fl == 21) - talk(_text[_lang][441], "441.als"); - else - hay_respuesta = 0; - } - } else { - if (num_ejec == 1) { - if (objeto_que_lleva == LOOK && fl == 50) - talk(_text[_lang][308], "308.als"); - else if (objeto_que_lleva == OPEN && fl == 50) - talk(_text[_lang][310], "310.als"); - else if (objeto_que_lleva == CLOSE && fl == 50) - talk(_text[_lang][311], "311.als"); - else if (objeto_que_lleva == MOVE && fl == 50) - talk(_text[_lang][312], "312.als"); - else if (objeto_que_lleva == PICK && fl == 50) - talk(_text[_lang][313], "313.als"); - else if (objeto_que_lleva == TALK && fl == 50) - talk(_text[_lang][314], "314.als"); - else if (!strcmp(num_room, "62.alg")) - room_62(fl); - else if (!strcmp(num_room, "63.alg")) - room_63(fl); - else - hay_respuesta = 0; - } else if (num_ejec == 2) { - if (objeto_que_lleva == LOOK && fl == 50) - talk(_text[_lang][308], "308.als"); - else if (objeto_que_lleva == OPEN && fl == 50) - talk(_text[_lang][310], "310.als"); - else if (objeto_que_lleva == CLOSE && fl == 50) - talk(_text[_lang][311], "311.als"); - else if (objeto_que_lleva == MOVE && fl == 50) - talk(_text[_lang][312], "312.als"); - else if (objeto_que_lleva == PICK && fl == 50) - talk(_text[_lang][313], "313.als"); - else if (objeto_que_lleva == TALK && fl == 50) - talk(_text[_lang][314], "314.als"); - else if (objeto_que_lleva == 11 && fl == 50 && flags[22] == 0 && strcmp(num_room, "18.alg")) - talk(_text[_lang][315], "315.als"); - else if (objeto_que_lleva == 13 && fl == 50) - talk(_text[_lang][156], "156.als"); - else if (objeto_que_lleva == 20 && fl == 50) - talk(_text[_lang][163], "163.als"); - else if (!strcmp(num_room, "1.alg")) - room_1(fl); - else if (!strcmp(num_room, "3.alg")) - room_3(fl); - else if (!strcmp(num_room, "4.alg")) - room_4(fl); - else if (!strcmp(num_room, "5.alg")) - room_5(fl); - else if (!strcmp(num_room, "6.alg")) - room_6(fl); - else if (!strcmp(num_room, "7.alg")) - room_7(fl); - else if (!strcmp(num_room, "8.alg")) - room_8(fl); - else if (!strcmp(num_room, "9.alg")) - room_9(fl); - else if (!strcmp(num_room, "12.alg")) - room_12(fl); - else if (!strcmp(num_room, "14.alg")) - room_14(fl); - else if (!strcmp(num_room, "15.alg")) - room_15(fl); - else if (!strcmp(num_room, "16.alg")) - room_16(fl); - else if (!strcmp(num_room, "17.alg")) - room_17(fl); - else if (!strcmp(num_room, "18.alg")) - room_18(fl); - else if (!strcmp(num_room, "19.alg")) - room_19(fl); - else - hay_respuesta = 0; - } else if (num_ejec == 3) { - if (objeto_que_lleva == LOOK && fl == 50) - talk(_text[_lang][309], "309.als"); - else if (objeto_que_lleva == OPEN && fl == 50) - talk(_text[_lang][310], "310.als"); - else if (objeto_que_lleva == CLOSE && fl == 50) - talk(_text[_lang][311], "311.als"); - else if (objeto_que_lleva == MOVE && fl == 50) - talk(_text[_lang][312], "312.als"); - else if (objeto_que_lleva == PICK && fl == 50) - talk(_text[_lang][313], "313.als"); - else if (objeto_que_lleva == TALK && fl == 50) - talk(_text[_lang][314], "314.als"); - else if (!strcmp(num_room, "13.alg")) { - if (room_13(fl)) - return true; - } else - hay_respuesta = 0; - } else if (num_ejec == 4) { - if (!strcmp(num_room, "28.alg")) - talk(_text[_lang][178], "178.als"); - else if (objeto_que_lleva == LOOK && fl == 50) - talk(_text[_lang][309], "309.als"); - else if (objeto_que_lleva == OPEN && fl == 50) - talk(_text[_lang][310], "310.als"); - else if (objeto_que_lleva == CLOSE && fl == 50) - talk(_text[_lang][311], "311.als"); - else if (objeto_que_lleva == MOVE && fl == 50) - talk(_text[_lang][312], "312.als"); - else if (objeto_que_lleva == PICK && fl == 50) - talk(_text[_lang][313], "313.als"); - else if (objeto_que_lleva == TALK && fl == 50) - talk(_text[_lang][314], "314.als"); - else if (objeto_que_lleva == 8 && fl == 50 && flags[18] == 0) - talk(_text[_lang][481], "481.als"); - else if (objeto_que_lleva == 9 && fl == 50) - talk(_text[_lang][484], "484.als"); - else if (objeto_que_lleva == 12 && fl == 50 && flags[18] == 0) - talk(_text[_lang][487], "487.als"); - else if (objeto_que_lleva == 20 && fl == 50) - talk(_text[_lang][487], "487.als"); - else if (!strcmp(num_room, "21.alg")) { - if (room_21(fl)) - return true; - } else if (!strcmp(num_room, "22.alg")) - room_22(fl); - else if (!strcmp(num_room, "23.alg")) - room_23(fl); - else if (!strcmp(num_room, "24.alg")) - room_24(fl); - else if (!strcmp(num_room, "26.alg")) - room_26(fl); - else if (!strcmp(num_room, "27.alg")) - room_27(fl); - else if (!strcmp(num_room, "29.alg")) - room_29(fl); - else if (!strcmp(num_room, "30.alg")) - room_30(fl); - else if (!strcmp(num_room, "31.alg")) - room_31(fl); - else if (!strcmp(num_room, "34.alg")) - room_34(fl); - else if (!strcmp(num_room, "35.alg")) - room_35(fl); - else if (!strcmp(num_room, "44.alg")) - room_44(fl); - else - hay_respuesta = 0; - } else if (num_ejec == 5) { - if (objeto_que_lleva == LOOK && fl == 50) - talk("Cuanto mas me miro, mas me gusto", "54.als"); - else if (objeto_que_lleva == OPEN && fl == 50) - talk("y luego como me cierro", "19.als"); - else if (objeto_que_lleva == CLOSE && fl == 50) - talk("Tendre que abrirme primero no", "19.als"); - else if (objeto_que_lleva == MOVE && fl == 50) - talk("Estoy bien donde estoy", "19.als"); - else if (objeto_que_lleva == PICK && fl == 50) - talk("Ya me tengo", "11.als"); - else if (objeto_que_lleva == TALK && fl == 50) - talk("hola yo", "16.als"); - else if (objeto_que_lleva == 20 && fl == 50) - talk(_text[_lang][487], "487.als"); - else if (!strcmp(num_room, "49.alg")) - room_49(fl); - else if (!strcmp(num_room, "53.alg")) - room_53(fl); - else if (!strcmp(num_room, "54.alg")) - room_54(fl); - else if (!strcmp(num_room, "55.alg")) - room_55(fl); - else if (!strcmp(num_room, "56.alg")) { - if (room_56(fl)) - return true; - } else - hay_respuesta = 0; - } else if (num_ejec == 6) { - if (objeto_que_lleva == LOOK && fl == 50 && flags[0] == 1) - talk(_text[_lang][308], "308.als"); - else if (objeto_que_lleva == LOOK && fl == 50 && flags[0] == 0) - talk(_text[_lang][310], "250.als" ); - else if (objeto_que_lleva == OPEN && fl == 50) - talk(_text[_lang][310], "310.als" ); - else if (objeto_que_lleva == CLOSE && fl == 50) - talk(_text[_lang][311], "311.als" ); - else if (objeto_que_lleva == MOVE && fl == 50) - talk(_text[_lang][312], "312.als" ); - else if (objeto_que_lleva == PICK && fl == 50) - talk(_text[_lang][313], "313.als" ); - else if (objeto_que_lleva == TALK && fl == 50) - talk(_text[_lang][314], "314.als" ); - else if (!strcmp(num_room, "102.alg")) - room_pendulo(fl); - else if (!strcmp(num_room, "58.alg")) - room_58(fl); - else if (!strcmp(num_room, "59.alg")) - room_59(fl); - else if (!strcmp(num_room, "60.alg")) { - if (room_60(fl)) - return true; - } else if (!strcmp(num_room, "61.alg")) - room_61(fl); - else - hay_respuesta = 0; - } - } - if (hay_respuesta == 0 && hay_nombre == 1) - room_0(); - else if (hay_respuesta == 0 && menu_scr == 1) - room_0(); - - return false; -} + y--; -void DrasculaEngine::cursor_mesa() { - int pos_cursor[8]; - - pos_cursor[0] = 225; - pos_cursor[1] = 56; - pos_cursor[2] = x_raton - 20; - pos_cursor[3] = y_raton - 12; - pos_cursor[4] = 40; - pos_cursor[5] = 25; - - copyRectClip(pos_cursor, dir_mesa, dir_zona_pantalla); -} - -void DrasculaEngine::introduce_nombre() { - Common::KeyCode key; - int v = 0, h = 0; - char select2[23]; - strcpy(select2, " "); - for (;;) { - buffer_teclado(); - select2[v] = '-'; - copyBackground(115, 14, 115, 14, 176, 9, dir_dibujo1, dir_zona_pantalla); - print_abc(select2, 117, 15); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - key = getscan(); - delay(70); - if (key != 0) { - if (key == Common::KEYCODE_q) - select2[v] = 'q'; - else if (key == Common::KEYCODE_w) - select2[v] = 'w'; - else if (key == Common::KEYCODE_e) - select2[v] = 'e'; - else if (key == Common::KEYCODE_r) - select2[v] = 'r'; - else if (key == Common::KEYCODE_t) - select2[v] = 't'; - else if (key == Common::KEYCODE_y) - select2[v] = 'y'; - else if (key == Common::KEYCODE_u) - select2[v] = 'u'; - else if (key == Common::KEYCODE_i) - select2[v] = 'i'; - else if (key == Common::KEYCODE_o) - select2[v] = 'o'; - else if (key == Common::KEYCODE_p) - select2[v] = 'p'; - else if (key == Common::KEYCODE_a) - select2[v] = 'a'; - else if (key == Common::KEYCODE_s) - select2[v] = 's'; - else if (key == Common::KEYCODE_d) - select2[v] = 'd'; - else if (key == Common::KEYCODE_f) - select2[v] = 'f'; - else if (key == Common::KEYCODE_g) - select2[v] = 'g'; - else if (key == Common::KEYCODE_h) - select2[v] = 'h'; - else if (key == Common::KEYCODE_j) - select2[v] = 'j'; - else if (key == Common::KEYCODE_k) - select2[v] = 'k'; - else if (key == Common::KEYCODE_l) - select2[v] = 'l'; - else if ((key == Common::KEYCODE_LCTRL) || (key == Common::KEYCODE_RCTRL)) - select2[v] = '\164'; - else if (key == Common::KEYCODE_z) - select2[v] = 'z'; - else if (key == Common::KEYCODE_x) - select2[v] = 'x'; - else if (key == Common::KEYCODE_c) - select2[v] = 'c'; - else if (key == Common::KEYCODE_v) - select2[v] = 'v'; - else if (key == Common::KEYCODE_b) - select2[v] = 'b'; - else if (key == Common::KEYCODE_n) - select2[v] = 'n'; - else if (key == Common::KEYCODE_m) - select2[v] = 'm'; - else if (key == Common::KEYCODE_1) - select2[v] = '1'; - else if (key == Common::KEYCODE_2) - select2[v] = '2'; - else if (key == Common::KEYCODE_3) - select2[v] = '3'; - else if (key == Common::KEYCODE_4) - select2[v] = '4'; - else if (key == Common::KEYCODE_5) - select2[v] = '5'; - else if (key == Common::KEYCODE_6) - select2[v] = '6'; - else if (key == Common::KEYCODE_7) - select2[v] = '7'; - else if (key == Common::KEYCODE_8) - select2[v] = '8'; - else if (key == Common::KEYCODE_9) - select2[v] = '9'; - else if (key == Common::KEYCODE_0) - select2[v] = '0'; - else if (key == Common::KEYCODE_SPACE) - select2[v] = '\167'; - else if (key == ESC) - break; - else if (key == Common::KEYCODE_RETURN) { - select2[v] = '\0'; - h = 1; - break; - } else if (key == Common::KEYCODE_BACKSPACE) - select2[v] = '\0'; - else - v--; - - if (key == Common::KEYCODE_BACKSPACE) - v--; - else - v++; - } - if (v == 22) - v = 21; - else if (v == -1) - v = 0; - } - if (h == 1) { - strcpy(select, select2); - hay_seleccion = 1; - } -} - -void DrasculaEngine::para_grabar(char nom_game[]) { - graba_partida(nom_game); - comienza_sound("99.als"); - fin_sound(); -} - -void DrasculaEngine::OpenSSN(const char *Name, int Pause) { - MiVideoSSN = (byte *)malloc(64256); - GlobalSpeed = 1000 / Pause; - FrameSSN = 0; - UsingMem = 0; - if (MiVideoSSN == NULL) - return; - _Sesion = new Common::File; - _Sesion->open(Name); - mSesion = TryInMem(_Sesion); - LastFrame = _system->getMillis(); -} - -int DrasculaEngine::PlayFrameSSN() { - int Exit = 0; - int Lengt; - byte *BufferSSN; - - if (!UsingMem) - _Sesion->read(&CHUNK, 1); - else { - memcpy(&CHUNK, mSesion, 1); - mSesion += 1; - } - switch (CHUNK) { - case SET_PALET: - if (!UsingMem) - _Sesion->read(dacSSN, 768); - else { - memcpy(dacSSN, mSesion, 768); - mSesion += 768; - } - set_dacSSN(dacSSN); - break; - case EMPTY_FRAME: - WaitFrameSSN(); - break; - case INIT_FRAME: - if (!UsingMem) { - _Sesion->read(&CMP, 1); - _Sesion->read(&Lengt, 4); + if (currentChapter == 3) { + if (y == 1) + trackCharacter = 1; + if (y == -1) + trackCharacter = 0; } else { - memcpy(&CMP, mSesion, 1); - mSesion += 1; - memcpy(&Lengt, mSesion, 4); - mSesion += 4; + if (y == 2) + trackCharacter = 1; + if (y == 0) + trackCharacter = 0; } - if (CMP == CMP_RLE) { - if (!UsingMem) { - BufferSSN = (byte *)malloc(Lengt); - _Sesion->read(BufferSSN, Lengt); - } else { - BufferSSN = (byte *)malloc(Lengt); - memcpy(BufferSSN, mSesion, Lengt); - mSesion += Lengt; - } - Des_RLE(BufferSSN, MiVideoSSN); - free(BufferSSN); - if (FrameSSN) { - WaitFrameSSN(); - MixVideo(VGA, MiVideoSSN); - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - } else { - WaitFrameSSN(); - memcpy(VGA, MiVideoSSN, 64000); - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - } - _system->updateScreen(); - FrameSSN++; - } else { - if (CMP == CMP_OFF) { - if (!UsingMem) { - BufferSSN = (byte *)malloc(Lengt); - _Sesion->read(BufferSSN, Lengt); - } else { - BufferSSN = (byte *)malloc(Lengt); - memcpy(BufferSSN, mSesion, Lengt); - mSesion += Lengt; - } - Des_OFF(BufferSSN, MiVideoSSN, Lengt); - free(BufferSSN); - if (FrameSSN) { - WaitFrameSSN(); - MixVideo(VGA, MiVideoSSN); - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - } else { - WaitFrameSSN(); - memcpy(VGA, MiVideoSSN, 64000); - _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); - } - _system->updateScreen(); - FrameSSN++; - } - } - break; - case END_ANIM: - Exit = 1; - break; - default: - Exit = 1; - break; - } + } while (counter > 0); - return (!Exit); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); } -void DrasculaEngine::EndSSN() { - free(MiVideoSSN); - if (UsingMem) - free(pointer); - else { - _Sesion->close(); - delete _Sesion; - } -} - -byte *DrasculaEngine::TryInMem(Common::File *Sesion) { - int Lengt; - - Sesion->seek(0, SEEK_END); - Lengt = Sesion->pos(); - Sesion->seek(0, SEEK_SET); - pointer = (byte *)malloc(Lengt); - if (pointer == NULL) - return NULL; - Sesion->read(pointer, Lengt); - UsingMem = 1; - Sesion->close(); - delete Sesion; - return pointer; -} - -void DrasculaEngine::set_dacSSN(byte *PalBuf) { - setvgapalette256((byte *)PalBuf); -} - -void DrasculaEngine::Des_OFF(byte *BufferOFF, byte *MiVideoOFF, int Lenght) { - int x = 0; - unsigned char Reps; - int Offset; - - memset(MiVideoSSN, 0, 64000); - while (x < Lenght) { - Offset = BufferOFF[x] + BufferOFF[x + 1] * 256; - Reps = BufferOFF[x + 2]; - memcpy(MiVideoOFF + Offset, &BufferOFF[x + 3], Reps); - x += 3 + Reps; - } -} - -void DrasculaEngine::Des_RLE(byte *BufferRLE, byte *MiVideoRLE) { - signed int con = 0; - unsigned int X = 0; - unsigned int fExit = 0; - char ch, rep; - while (!fExit) { - ch = *BufferRLE++; - rep = 1; - if ((ch & 192) == 192) { - rep = (ch & 63); - ch =* BufferRLE++; - } - for (con = 0; con < rep; con++) { - *MiVideoRLE++ = ch; - X++; - if (X > 64000) - fExit = 1; - } - } -} - -void DrasculaEngine::MixVideo(byte *OldScreen, byte *NewScreen) { - int x; - for (x = 0; x < 64000; x++) - OldScreen[x] ^= NewScreen[x]; -} - -void DrasculaEngine::WaitFrameSSN() { - uint32 now; - while ((now = _system->getMillis()) - LastFrame < ((uint32) GlobalSpeed)) - _system->delayMillis(GlobalSpeed - (now - LastFrame)); - LastFrame = LastFrame + GlobalSpeed; -} - -byte *DrasculaEngine::carga_pcx(byte *NamePcc) { - signed int con = 0; - unsigned int X = 0; - unsigned int fExit = 0; - char ch, rep; - byte *AuxPun; - - AuxPun = AuxBuffDes; - - while (!fExit) { - ch = *NamePcc++; - rep = 1; - if ((ch & 192) == 192) { - rep = (ch & 63); - ch = *NamePcc++; - } - for (con = 0; con< rep; con++) { - *AuxPun++ = ch; - X++; - if (X > 64000) - fExit = 1; - } - } - return AuxBuffDes; -} - -void DrasculaEngine::set_dac(byte *dac) { - setvgapalette256((byte *)dac); -} - -void DrasculaEngine::WaitForNext(int FPS) { - _system->delayMillis(1000 / FPS); -} - -int DrasculaEngine::vez() { - return _system->getMillis() / 20; // originaly was 1 -} - -void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int ancho, int alto, int factor, byte *dir_inicio, byte *dir_fin) { - float suma_x, suma_y; - int n, m; - float pixel_x, pixel_y; - int pos_pixel[6]; - - nuevo_ancho = (ancho * factor) / 100; - nuevo_alto = (alto * factor) / 100; - - suma_x = ancho / nuevo_ancho; - suma_y = alto / nuevo_alto; - - pixel_x = xx1; - pixel_y = yy1; - - for (n = 0; n < nuevo_alto; n++) { - for (m = 0; m < nuevo_ancho; m++) { - pos_pixel[0] = (int)pixel_x; - pos_pixel[1] = (int)pixel_y; - pos_pixel[2] = xx2 + m; - pos_pixel[3] = yy2 + n; - pos_pixel[4] = 1; - pos_pixel[5] = 1; - - copyRectClip(pos_pixel, dir_inicio, dir_fin); - - pixel_x = pixel_x + suma_x; - } - pixel_x = xx1; - pixel_y = pixel_y + suma_y; - } -} - -char DrasculaEngine::codifica(char car) { - return ~car; -} - -void DrasculaEngine::cuadrante_1() { - float distancia_x, distancia_y; - - if (num_ejec == 2) - distancia_x = hare_x - sitio_x; - else - distancia_x = hare_x + ancho_hare / 2 - sitio_x; - - distancia_y = (hare_y + alto_hare) - sitio_y; - - if (distancia_x < distancia_y) { - direccion_hare = 0; - sentido_hare = 2; - paso_x = (int)(distancia_x / (distancia_y / PASO_HARE_Y)); - } else { - direccion_hare = 7; - sentido_hare = 0; - paso_y = (int)(distancia_y / (distancia_x / PASO_HARE_X)); - } -} - -void DrasculaEngine::cuadrante_2() { - float distancia_x, distancia_y; - - if (num_ejec == 2) - distancia_x = abs(hare_x + ancho_hare - sitio_x); - else - distancia_x = abs(hare_x + ancho_hare / 2 - sitio_x); - - distancia_y = (hare_y + alto_hare) - sitio_y; - - if (distancia_x < distancia_y) { - direccion_hare = 1; - sentido_hare = 2; - paso_x = (int)(distancia_x / (distancia_y / PASO_HARE_Y)); - } else { - direccion_hare = 2; - sentido_hare = 1; - paso_y = (int)(distancia_y / (distancia_x / PASO_HARE_X)); - } -} - -void DrasculaEngine::cuadrante_3() { - float distancia_x, distancia_y; - - if (num_ejec == 2) - distancia_x = hare_x - sitio_x; - else - distancia_x = hare_x + ancho_hare / 2 - sitio_x; - - distancia_y = sitio_y - (hare_y + alto_hare); - - if (distancia_x < distancia_y) { - direccion_hare = 5; - sentido_hare = 3; - paso_x = (int)(distancia_x / (distancia_y / PASO_HARE_Y)); - } else { - direccion_hare = 6; - sentido_hare = 0; - paso_y = (int)(distancia_y / (distancia_x / PASO_HARE_X)); - } -} - -void DrasculaEngine::cuadrante_4() { - float distancia_x, distancia_y; - - if (num_ejec == 2) - distancia_x = abs(hare_x + ancho_hare - sitio_x); - else - distancia_x = abs(hare_x + ancho_hare / 2 - sitio_x); - - distancia_y = sitio_y - (hare_y + alto_hare); - - if (distancia_x < distancia_y) { - direccion_hare = 4; - sentido_hare = 3; - paso_x = (int)(distancia_x / (distancia_y / PASO_HARE_Y)); - } else { - direccion_hare = 3; - sentido_hare = 1; - paso_y = (int)(distancia_y / (distancia_x / PASO_HARE_X)); - } -} - -void DrasculaEngine::graba_partida(char nom_game[]) { - Common::OutSaveFile *out; - int l; - - if (!(out = _saveFileMan->openForSaving(nom_game))) { - error("no puedo abrir el archivo"); - } - out->writeSint32LE(num_ejec); - out->write(datos_actuales, 20); - out->writeSint32LE(hare_x); - out->writeSint32LE(hare_y); - out->writeSint32LE(sentido_hare); - - for (l = 1; l < 43; l++) { - out->writeSint32LE(objetos_que_tengo[l]); - } - - for (l = 0; l < NUM_BANDERAS; l++) { - out->writeSint32LE(flags[l]); - } - - out->writeSint32LE(lleva_objeto); - out->writeSint32LE(objeto_que_lleva); - - out->finalize(); - if (out->ioFailed()) - warning("Can't write file '%s'. (Disk full?)", nom_game); - - delete out; -} - -void DrasculaEngine::aumenta_num_frame() { - diff_vez = vez() - conta_vez; - - if (diff_vez >= 6) { - conta_vez = vez(); - num_frame++; - if (num_frame == 6) - num_frame = 0; - - if (direccion_hare == 0) { - hare_x = hare_x - paso_x; - hare_y = hare_y - paso_y; - } else if (direccion_hare == 7) { - hare_x = hare_x - paso_x; - hare_y = hare_y - paso_y; - } else if (direccion_hare == 1) { - hare_x = hare_x + paso_x; - hare_y = hare_y - paso_y; - } else if (direccion_hare == 2) { - hare_x = hare_x + paso_x; - hare_y = hare_y - paso_y; - } else if (direccion_hare == 3) { - hare_x = hare_x + paso_x; - hare_y = hare_y + paso_y; - } else if (direccion_hare == 4) { - hare_x = hare_x + paso_x; - hare_y = hare_y + paso_y; - } else if (direccion_hare == 5) { - hare_x = hare_x - paso_x; - hare_y = hare_y + paso_y; - } else if (direccion_hare == 6) { - hare_x = hare_x - paso_x; - hare_y = hare_y + paso_y; - } - } - - if (num_ejec != 2) { - diferencia_y = (int)(alto_hare - nuevo_alto); - diferencia_x = (int)(ancho_hare - nuevo_ancho); - hare_y = hare_y + diferencia_y; - hare_x = hare_x + diferencia_x; - alto_hare = (int)nuevo_alto; - ancho_hare = (int)nuevo_ancho; - } -} - -int DrasculaEngine::sobre_que_objeto() { - int n = 0; - - for (n = 1; n < 43; n++) { - if (x_raton > x_obj[n] && y_raton > y_obj[n] - && x_raton < x_obj[n] + ANCHOBJ && y_raton < y_obj[n] + ALTOBJ) - break; - } - - return n; -} - -bool DrasculaEngine::comprueba_banderas_menu() { - int h, n; - - for (n = 0; n < 43; n++) { - if (sobre_que_objeto() == n) { - h = objetos_que_tengo[n]; - if (h != 0) - if (banderas(h)) - return true; - } - } - - return false; -} - -void DrasculaEngine::conversa(const char *nom_fich) { - int h; - int juego1 = 1, juego2 = 1, juego3 = 1, juego4 = 1; - char frase1[78]; - char frase2[78]; - char frase3[87]; - char frase4[78]; - char para_codificar[13]; - char suena1[13]; - char suena2[13]; - char suena3[13]; - char suena4[13]; - int longitud; - int respuesta1; - int respuesta2; - int respuesta3; - int usado1 = 0; - int usado2 = 0; - int usado3 = 0; - char buffer[256]; - - rompo_y_salgo = 0; - - strcpy(para_codificar, nom_fich); - - if (num_ejec == 5) - sin_verbo(); - - ald = new Common::File; - ald->open(nom_fich); - if (!ald->isOpen()) { - error("missing data file"); - } - int size = ald->size(); - - getLine(ald, buffer, size); - sscanf(buffer, "%s", frase1); - getLine(ald, buffer, size); - sscanf(buffer, "%s", frase2); - getLine(ald, buffer, size); - sscanf(buffer, "%s", frase3); - getLine(ald, buffer, size); - sscanf(buffer, "%s", frase4); - getLine(ald, buffer, size); - sscanf(buffer, "%s", suena1); - getLine(ald, buffer, size); - sscanf(buffer, "%s", suena2); - getLine(ald, buffer, size); - sscanf(buffer, "%s", suena3); - getLine(ald, buffer, size); - sscanf(buffer, "%s", suena4); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &respuesta1); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &respuesta2); - getLine(ald, buffer, size); - sscanf(buffer, "%d", &respuesta3); - delete ald; - ald = NULL; - - if (num_ejec == 2 && !strcmp(nom_fich, "op_5.cal") && flags[38] == 1 && flags[33] == 1) { - strcpy(frase3, _text[_lang][405]); - strcpy(suena3, "405.als"); - respuesta3 = 31; - } - - if (num_ejec == 6 && !strcmp(nom_fich, "op_12.cal") && flags[7] == 1) { - strcpy(frase3, _text[_lang][273]); - strcpy(suena3, "273.als"); - respuesta3 = 14; - } - - if (num_ejec == 6 && !strcmp(nom_fich, "op_12.cal") && flags[10] == 1) { - strcpy(frase3, " cuanto queda para que acabe el partido?"); - strcpy(suena3, "274.als"); - respuesta3 = 15; - } - - longitud = strlen(frase1); - for (h = 0; h < longitud; h++) - if (frase1[h] == (char)0xa7) - frase1[h] = ' '; - - longitud = strlen(frase2); - for (h = 0; h < longitud; h++) - if (frase2[h] == (char)0xa7) - frase2[h] = ' '; - - longitud = strlen(frase3); - for (h = 0; h < longitud; h++) - if (frase3[h] == (char)0xa7) - frase3[h] = ' '; - - longitud = strlen(frase4); - for (h = 0; h < longitud; h++) - if (frase4[h] == (char)0xa7) - frase4[h] = ' '; - - loadPic("car.alg"); - decompressPic(dir_hare_fondo, 1); - // TODO code here should limit y position for mouse in dialog menu, - // but we can't implement this due lack backend functionality - // from 1(top) to 31 - color_abc(VERDE_CLARO); - -bucle_opc: - - updateRoom(); - - if (num_ejec == 1 || num_ejec == 4 || num_ejec == 6) { - if (music_status() == 0 && flags[11] == 0) - playmusic(musica_room); - } else if (num_ejec == 2) { - if (music_status() == 0 && flags[11] == 0 && musica_room != 0) - playmusic(musica_room); - } else if (num_ejec == 3 || num_ejec == 5) { - if (music_status() == 0) - playmusic(musica_room); - } - - MirarRaton(); - - if (y_raton > 0 && y_raton < 9) { - if (usado1 == 1 && _color != BLANCO) - color_abc(BLANCO); - else if (usado1 == 0 && _color != VERDE_CLARO) - color_abc(VERDE_CLARO); - } else if (y_raton > 8 && y_raton < 17) { - if (usado2 == 1 && _color != BLANCO) - color_abc(BLANCO); - else if (usado2 == 0 && _color != VERDE_CLARO) - color_abc(VERDE_CLARO); - } else if (y_raton > 16 && y_raton < 25) { - if (usado3 == 1 && _color != BLANCO) - color_abc(BLANCO); - else if (usado3 == 0 && _color != VERDE_CLARO) - color_abc(VERDE_CLARO); - } else if (_color != VERDE_CLARO) - color_abc(VERDE_CLARO); - - if (y_raton > 0 && y_raton < 9) - juego1 = 2; - else if (y_raton > 8 && y_raton < 17) - juego2 = 2; - else if (y_raton > 16 && y_raton < 25) - juego3 = 2; - else if (y_raton > 24 && y_raton < 33) - juego4 = 2; - - print_abc_opc(frase1, 1, 2, juego1); - print_abc_opc(frase2, 1, 10, juego2); - print_abc_opc(frase3, 1, 18, juego3); - print_abc_opc(frase4, 1, 26, juego4); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - if ((boton_izq == 1) && (juego1 == 2)) { - delay(100); - usado1 = 1; - talk(frase1, suena1); - if (num_ejec == 3) - grr(); - else - responde(respuesta1); - } else if ((boton_izq == 1) && (juego2 == 2)) { - delay(100); - usado2 = 1; - talk(frase2, suena2); - if (num_ejec == 3) - grr(); - else - responde(respuesta2); - } else if ((boton_izq == 1) && (juego3 == 2)) { - delay(100); - usado3 = 1; - talk(frase3, suena3); - if (num_ejec == 3) - grr(); - else - responde(respuesta3); - } else if ((boton_izq == 1) && (juego4 == 2)) { - delay(100); - talk(frase4, suena4); - rompo_y_salgo = 1; - } - - if (boton_izq == 1) { - delay(100); - color_abc(VERDE_CLARO); - } - - if (usado1 == 0) - juego1 = 1; - else - juego1 = 3; - if (usado2 == 0) - juego2 = 1; - else - juego2 = 3; - if (usado3 == 0) - juego3 = 1; - else - juego3 = 3; - - juego4 = 1; - - if (rompo_y_salgo == 0) - goto bucle_opc; - - if (num_ejec == 2) - loadPic(fondo_y_menu); - else - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - if (num_ejec != 5) - sin_verbo(); -} - -void DrasculaEngine::print_abc_opc(const char *dicho, int x_pantalla, int y_pantalla, int juego) { - int pos_texto[6]; - int y_de_signos, y_de_letra, x_de_letra = 0, h, longitud; - longitud = strlen(dicho); - - for (h = 0; h < longitud; h++) { - if (juego == 1) { - y_de_letra = Y_ABC_OPC_1; - y_de_signos = Y_SIGNOS_OPC_1; - } else if (juego == 3) { - y_de_letra = Y_ABC_OPC_3; - y_de_signos = Y_SIGNOS_OPC_3; - } else { - y_de_letra = Y_ABC_OPC_2; - y_de_signos = Y_SIGNOS_OPC_2; - } - - int c = toupper(dicho[h]); - if (c == 'A') - x_de_letra = X_A_OPC; - else if (c == 'B') - x_de_letra = X_B_OPC; - else if (c == 'C') - x_de_letra = X_C_OPC; - else if (c == 'D') - x_de_letra = X_D_OPC; - else if (c == 'E') - x_de_letra = X_E_OPC; - else if (c == 'F') - x_de_letra = X_F_OPC; - else if (c == 'G') - x_de_letra = X_G_OPC; - else if (c == 'H') - x_de_letra = X_H_OPC; - else if (c == 'I') - x_de_letra = X_I_OPC; - else if (c == 'J') - x_de_letra = X_J_OPC; - else if (c == 'K') - x_de_letra = X_K_OPC; - else if (c == 'L') - x_de_letra = X_L_OPC; - else if (c == 'M') - x_de_letra = X_M_OPC; - else if (c == 'N') - x_de_letra = X_N_OPC; - else if (c == 'O') - x_de_letra = X_O_OPC; - else if (c == 'P') - x_de_letra = X_P_OPC; - else if (c == 'Q') - x_de_letra = X_Q_OPC; - else if (c == 'R') - x_de_letra = X_R_OPC; - else if (c == 'S') - x_de_letra = X_S_OPC; - else if (c == 'T') - x_de_letra = X_T_OPC; - else if (c == 'U') - x_de_letra = X_U_OPC; - else if (c == 'V') - x_de_letra = X_V_OPC; - else if (c == 'W') - x_de_letra = X_W_OPC; - else if (c == 'X') - x_de_letra = X_X_OPC; - else if (c == 'Y') - x_de_letra = X_Y_OPC; - else if (c == 'Z') - x_de_letra = X_Z_OPC; - else if (c == ' ') - x_de_letra = ESPACIO_OPC; - else { - y_de_letra = y_de_signos; - if (c == '.') - x_de_letra = X_PUNTO_OPC; - else if (c == ',') - x_de_letra = X_COMA_OPC; - else if (c == '-') - x_de_letra = X_GUION_OPC; - else if (c == '?') - x_de_letra = X_CIERRA_INTERROGACION_OPC; - else if (c == 0xa8) - x_de_letra = X_ABRE_INTERROGACION_OPC; -// else if (c == '\'') // FIXME -// x_de_letra = ESPACIO; // space for now - else if (c == '"') - x_de_letra = X_COMILLAS_OPC; - else if (c == '!') - x_de_letra = X_CIERRA_INTERROGACION_OPC; - else if (c == 0xad) - x_de_letra = X_ABRE_EXCLAMACION_OPC; - else if (c == ';') - x_de_letra = X_PUNTO_Y_COMA_OPC; - else if (c == '>') - x_de_letra = X_MAYOR_QUE_OPC; - else if (c == '<') - x_de_letra = X_MENOR_QUE_OPC; - else if (c == '$') - x_de_letra = X_DOLAR_OPC; - else if (c == '%') - x_de_letra = X_POR_CIENTO_OPC; - else if (c == ':') - x_de_letra = X_DOS_PUNTOS_OPC; - else if (c == '&') - x_de_letra = X_AND_OPC; - else if (c == '/') - x_de_letra = X_BARRA_OPC; - else if (c == '(') - x_de_letra = X_ABRE_PARENTESIS_OPC; - else if (c == ')') - x_de_letra = X_CIERRA_PARENTESIS_OPC; - else if (c == '*') - x_de_letra = X_ASTERISCO_OPC; - else if (c == '+') - x_de_letra = X_MAS_OPC; - else if (c == '1') - x_de_letra = X_N1_OPC; - else if (c == '2') - x_de_letra = X_N2_OPC; - else if (c == '3') - x_de_letra = X_N3_OPC; - else if (c == '4') - x_de_letra = X_N4_OPC; - else if (c == '5') - x_de_letra = X_N5_OPC; - else if (c == '6') - x_de_letra = X_N6_OPC; - else if (c == '7') - x_de_letra = X_N7_OPC; - else if (c == '8') - x_de_letra = X_N8_OPC; - else if (c == '9') - x_de_letra = X_N9_OPC; - else if (c == '0') - x_de_letra = X_N0_OPC; - } +bool DrasculaEngine::loadDrasculaDat() { + Common::File in; + int i; - pos_texto[0] = x_de_letra; - pos_texto[1] = y_de_letra; - pos_texto[2] = x_pantalla; - pos_texto[3] = y_pantalla; - pos_texto[4] = ANCHO_LETRAS_OPC; - pos_texto[5] = ALTO_LETRAS_OPC; + in.open("drascula.dat"); - copyRectClip(pos_texto, dir_hare_fondo, dir_zona_pantalla); + if (!in.isOpen()) { + Common::String errorMessage = "You're missing the 'drascula.dat' file. Get it from the ScummVM website"; + GUIErrorMessage(errorMessage); + warning(errorMessage.c_str()); - x_pantalla = x_pantalla + ANCHO_LETRAS_OPC; - } -} - -void DrasculaEngine::responde(int funcion) { - if (num_ejec == 1) { - if (funcion == 10) - talk_borracho(_textb[_lang][1], "B1.als"); - else if (funcion == 11) - talk_borracho(_textb[_lang][2], "B2.als"); - else if (funcion == 12) - talk_borracho(_textb[_lang][3], "B3.als"); - } else if (num_ejec == 2) { - if (funcion == 8) - animation_8_2(); - else if (funcion == 9) - animation_9_2(); - else if (funcion == 10) - animation_10_2(); - else if (funcion == 15) - animation_15_2(); - else if (funcion == 16) - animation_16_2(); - else if (funcion == 17) - animation_17_2(); - else if (funcion == 19) - animation_19_2(); - else if (funcion == 20) - animation_20_2(); - else if (funcion == 21) - animation_21_2(); - else if (funcion == 23) - animation_23_2(); - else if (funcion == 28) - animation_28_2(); - else if (funcion == 29) - animation_29_2(); - else if (funcion == 30) - animation_30_2(); - else if (funcion == 31) - animation_31_2(); - } else if (num_ejec == 4) { - if (funcion == 2) - animation_2_4(); - else if (funcion == 3) - animation_3_4(); - else if (funcion == 4) - animation_4_4(); - } else if (num_ejec == 5) { - if (funcion == 2) - animation_2_5(); - else if (funcion == 3) - animation_3_5(); - else if (funcion == 6) - animation_6_5(); - else if (funcion == 7) - animation_7_5(); - else if (funcion == 8) - animation_8_5(); - else if (funcion == 15) - animation_15_5(); - else if (funcion == 16) - animation_16_5(); - else if (funcion == 17) - animation_17_5(); - } else if (num_ejec == 6) { - if (funcion == 2) - animation_2_6(); - else if (funcion == 3) - animation_3_6(); - else if (funcion == 4) - animation_4_6(); - else if (funcion == 11) - animation_11_6(); - else if (funcion == 12) - animation_12_6(); - else if (funcion == 13) - animation_13_6(); - else if (funcion == 14) - animation_14_6(); - else if (funcion == 15) - animation_15_6(); + return false; } -} -void DrasculaEngine::suma_objeto(int osj) { - int h, puesto = 0; + char buf[256]; + int ver; - for (h = 1; h < 43; h++) { - if (objetos_que_tengo[h] == osj) - puesto = 1; - } + in.read(buf, 8); + buf[8] = '\0'; - if (puesto == 0) { - for (h = 1; h < 43; h++) { - if (objetos_que_tengo[h] == 0) { - objetos_que_tengo[h] = osj; - puesto = 1; - break; - } - } - } -} - -void DrasculaEngine::fin_sound_corte() { - if (hay_sb == 1) { - ctvd_stop(); - delete sku; - sku = NULL; - ctvd_terminate(); - } -} + if (strcmp(buf, "DRASCULA")) { + Common::String errorMessage = "File 'drascula.dat' is corrupt. Get it from the ScummVM website"; + GUIErrorMessage(errorMessage); + warning(errorMessage.c_str()); -void DrasculaEngine::MusicFadeout() { - int org_vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); - for (;;) { - int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); - vol -= 10; - if (vol < 0) - vol = 0; - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol); - if (vol == 0) - break; - update_events(); - _system->updateScreen(); - _system->delayMillis(50); + return false; } - AudioCD.stop(); - _system->delayMillis(100); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, org_vol); -} - -void DrasculaEngine::ctvd_end() { - _mixer->stopHandle(_soundHandle); -} - -void DrasculaEngine::ctvd_stop() { - _mixer->stopHandle(_soundHandle); -} - -void DrasculaEngine::ctvd_terminate() { -// _mixer->stopHandle(_soundHandle); -} -void DrasculaEngine::ctvd_speaker(int flag) {} - -void DrasculaEngine::ctvd_output(Common::File *file_handle) {} - -void DrasculaEngine::ctvd_init(int b) { - int soundSize = sku->size(); - byte *soundData = (byte *)malloc(soundSize); - sku->seek(32); - sku->read(soundData, soundSize); - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_soundHandle, soundData, soundSize - 64, - 11025, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); -} + ver = in.readByte(); + + if (ver != DRASCULA_DAT_VER) { + snprintf(buf, 256, "File 'drascula.dat' is wrong version. Expected %d but got %d. Get it from the ScummVM website", DRASCULA_DAT_VER, ver); + GUIErrorMessage(buf); + warning(buf); -int DrasculaEngine::LookForFree() { - return _mixer->isSoundHandleActive(_soundHandle); -} - -void DrasculaEngine::actualiza_datos() { - if (num_ejec == 1) { - // nothing - } else if (num_ejec == 2) { - if (!strcmp(num_room,"2.alg") && flags[40] == 0) - visible[3] = 0; - else if (!strcmp(num_room, "3.alg") && flags[3] == 1) - visible[8] = 0; - else if (!strcmp(num_room, "6.alg") && flags[1] == 1 && flags[10] == 0) { - visible[2] = 0; - visible[4] = 1; - } else if (!strcmp(num_room, "7.alg") && flags[35] == 1) - visible[3] = 0; - else if (!strcmp(num_room, "14.alg") && flags[5] == 1) - visible[4] = 0; - else if (!strcmp(num_room, "18.alg") && flags[28] == 1) - visible[2] = 0; - } else if (num_ejec == 3) { - // nothing - } else if (num_ejec == 4) { - if (!strcmp(num_room, "23.alg") && flags[0] == 0 && flags[11] == 0) - visible[2] = 1; - if (!strcmp(num_room, "23.alg") && flags[0] == 1 && flags[11] == 0) - visible[2] = 0; - if (!strcmp(num_room, "21.alg") && flags[10] == 1) - visible[2] = 0; - if (!strcmp(num_room, "22.alg") && flags[26] == 1) { - visible[2] = 0; - visible[1] = 1; - } - if (!strcmp(num_room, "22.alg") && flags[27] == 1) - visible[3] = 0; - if (!strcmp(num_room, "26.alg") && flags[21] == 0) - strcpy(nombre_obj[2], "HUNCHBACKED"); - if (!strcmp(num_room, "26.alg") && flags[18] == 1) - visible[2] = 0; - if (!strcmp(num_room, "26.alg") && flags[12] == 1) - visible[1] = 0; - if (!strcmp(num_room, "35.alg") && flags[14] == 1) - visible[2] = 0; - if (!strcmp(num_room, "35.alg") && flags[17] == 1) - visible[3] = 1; - if (!strcmp(num_room, "35.alg") && flags[15] == 1) - visible[1] = 0; - } else if (num_ejec == 5) { - if (!strcmp(num_room,"49.alg") && flags[6] == 1) - visible[2] = 0; - if (!strcmp(num_room,"49.alg") && flags[6] == 0) - visible[1] = 0; - if (!strcmp(num_room,"49.alg") && flags[6] == 1) - visible[1] = 1; - if (!strcmp(num_room,"45.alg") && flags[6] == 1) - visible[3] = 1; - if (!strcmp(num_room,"53.alg") && flags[2] == 1) - visible[3] = 0; - if (!strcmp(num_room,"54.alg") && flags[13] == 1) - visible[3] = 0; - if (!strcmp(num_room,"55.alg") && flags[8] == 1) - visible[1] = 0; - } else if (num_ejec == 6) { - if ((!strcmp(num_room, "58.alg")) && flags[8] == 0) - espuerta[1] = 0; - if ((!strcmp(num_room, "58.alg")) && flags[8] == 1) - espuerta[1] = 1; - if (!strcmp(num_room, "59.alg")) - espuerta[1] = 0; - if (!strcmp(num_room, "60.alg")) { - sentido_dr = 0; - x_dr = 155; - y_dr = 69; - } + return false; } -} -void DrasculaEngine::anda_pabajo() { - direccion_hare = 4; - sentido_hare = 3; - paso_x = 0; -} - -void DrasculaEngine::anda_parriba() { - direccion_hare = 0; - sentido_hare = 2; - paso_x = 0; -} - -void DrasculaEngine::pon_vb() { - int pos_vb[6]; - - if (vb_se_mueve == 0) { - pos_vb[0] = 256; - pos_vb[1] = 129; - pos_vb[2] = vb_x; - pos_vb[3] = 66; - pos_vb[4] = 33; - pos_vb[5] = 69; - if (sentido_vb == 0) - pos_vb[0] = 222; - else if (sentido_vb == 1) - pos_vb[0] = 188; - } else { - pos_vb[2] = vb_x; - pos_vb[3] = 66; - pos_vb[4] = 28; - pos_vb[5] = 68; - - if (sentido_vb == 0) { - pos_vb[0] = frame_vb; - pos_vb[1] = 62; - } else { - pos_vb[0] = frame_vb; - pos_vb[1] = 131; - } - - frame_vb = frame_vb + 29; - if (frame_vb > 146) - frame_vb = 1; + _charMapSize = in.readUint16BE(); + _charMap = (CharInfo *)malloc(sizeof(CharInfo) * _charMapSize); + for (i = 0; i < _charMapSize; i++) { + _charMap[i].inChar = in.readByte(); + _charMap[i].mappedChar = in.readSint16BE(); + _charMap[i].charType = in.readByte(); } - copyRectClip(pos_vb, dir_hare_frente, dir_zona_pantalla); -} - -void DrasculaEngine::lleva_vb(int punto_x) { - if (punto_x < vb_x) - sentido_vb = 0; - else - sentido_vb = 1; - - vb_se_mueve = 1; - - for (;;) { - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if (sentido_vb == 0) { - vb_x = vb_x - 5; - if (vb_x <= punto_x) - break; - } else { - vb_x = vb_x + 5; - if (vb_x >= punto_x) - break; - } - pause(5); - } + _itemLocationsSize = in.readUint16BE(); + _itemLocations = (ItemLocation *)malloc(sizeof(ItemLocation) * _itemLocationsSize); + for (i = 0; i < _itemLocationsSize; i++) { + _itemLocations[i].x = in.readSint16BE(); + _itemLocations[i].y = in.readSint16BE(); + } + + _polXSize = in.readUint16BE(); + _polX = (int *)malloc(sizeof(int) * _polXSize); + _polY = (int *)malloc(sizeof(int) * _polXSize); + for (i = 0; i < _polXSize; i++) { + _polX[i] = in.readSint16BE(); + _polY[i] = in.readSint16BE(); + } + + _verbBarXSize = in.readUint16BE(); + _verbBarX = (int *)malloc(sizeof(int) * _verbBarXSize); + for (i = 0; i < _verbBarXSize; i++) { + _verbBarX[i] = in.readSint16BE(); + } + + _x1dMenuSize = in.readUint16BE(); + _x1d_menu = (int *)malloc(sizeof(int) * _x1dMenuSize); + _y1d_menu = (int *)malloc(sizeof(int) * _x1dMenuSize); + for (i = 0; i < _x1dMenuSize; i++) { + _x1d_menu[i] = in.readSint16BE(); + _y1d_menu[i] = in.readSint16BE(); + } + + _frameXSize = in.readUint16BE(); + _frameX = (int *)malloc(sizeof(int) * _frameXSize); + for (i = 0; i < _frameXSize; i++) { + _frameX[i] = in.readSint16BE(); + } + + _candleXSize = in.readUint16BE(); + _candleX = (int *)malloc(sizeof(int) * _candleXSize); + _candleY = (int *)malloc(sizeof(int) * _candleXSize); + for (i = 0; i < _candleXSize; i++) { + _candleX[i] = in.readSint16BE(); + _candleY[i] = in.readSint16BE(); + } + + _pianistXSize = in.readUint16BE(); + _pianistX = (int *)malloc(sizeof(int) * _pianistXSize); + for (i = 0; i < _pianistXSize; i++) { + _pianistX[i] = in.readSint16BE(); + } + + _drunkXSize = in.readUint16BE(); + _drunkX = (int *)malloc(sizeof(int) * _drunkXSize); + for (i = 0; i < _drunkXSize; i++) { + _drunkX[i] = in.readSint16BE(); + } + + _roomPreUpdatesSize = in.readUint16BE(); + _roomPreUpdates = (RoomUpdate *)malloc(sizeof(RoomUpdate) * _roomPreUpdatesSize); + for (i = 0; i < _roomPreUpdatesSize; i++) { + _roomPreUpdates[i].roomNum = in.readSint16BE(); + _roomPreUpdates[i].flag = in.readSint16BE(); + _roomPreUpdates[i].flagValue = in.readSint16BE(); + _roomPreUpdates[i].sourceX = in.readSint16BE(); + _roomPreUpdates[i].sourceY = in.readSint16BE(); + _roomPreUpdates[i].destX = in.readSint16BE(); + _roomPreUpdates[i].destY = in.readSint16BE(); + _roomPreUpdates[i].width = in.readSint16BE(); + _roomPreUpdates[i].height = in.readSint16BE(); + _roomPreUpdates[i].type = in.readSint16BE(); + } + + _roomUpdatesSize = in.readUint16BE(); + _roomUpdates = (RoomUpdate *)malloc(sizeof(RoomUpdate) * _roomUpdatesSize); + for (i = 0; i < _roomUpdatesSize; i++) { + _roomUpdates[i].roomNum = in.readSint16BE(); + _roomUpdates[i].flag = in.readSint16BE(); + _roomUpdates[i].flagValue = in.readSint16BE(); + _roomUpdates[i].sourceX = in.readSint16BE(); + _roomUpdates[i].sourceY = in.readSint16BE(); + _roomUpdates[i].destX = in.readSint16BE(); + _roomUpdates[i].destY = in.readSint16BE(); + _roomUpdates[i].width = in.readSint16BE(); + _roomUpdates[i].height = in.readSint16BE(); + _roomUpdates[i].type = in.readSint16BE(); + } + + _roomActionsSize = in.readUint16BE(); + _roomActions = (RoomTalkAction *)malloc(sizeof(RoomTalkAction) * _roomActionsSize); + for (i = 0; i < _roomActionsSize; i++) { + _roomActions[i].room = in.readSint16BE(); + _roomActions[i].chapter = in.readSint16BE(); + _roomActions[i].action = in.readSint16BE(); + _roomActions[i].objectID = in.readSint16BE(); + _roomActions[i].speechID = in.readSint16BE(); + } + + _numLangs = in.readUint16BE(); + + _text = loadTexts(in); + _textd = loadTexts(in); + _textb = loadTexts(in); + _textbj = loadTexts(in); + _texte = loadTexts(in); + _texti = loadTexts(in); + _textl = loadTexts(in); + _textp = loadTexts(in); + _textt = loadTexts(in); + _textvb = loadTexts(in); + _textsys = loadTexts(in); + _texthis = loadTexts(in); + _textverbs = loadTexts(in); + _textmisc = loadTexts(in); + _textd1 = loadTexts(in); - vb_se_mueve = 0; + return true; } -void DrasculaEngine::hipo_sin_nadie(int contador){ - int y = 0, sentido = 0; - if (num_ejec == 3) - y = -1; +char ***DrasculaEngine::loadTexts(Common::File &in) { + int numTexts = in.readUint16BE(); + char ***res; + int entryLen; + char *pos; + int len; -comienza: - contador--; + res = (char ***)malloc(sizeof(char *) * _numLangs); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - if (num_ejec == 3) - updateScreen(0, 0, 0, y, 320, 200, dir_zona_pantalla); - else - updateScreen(0, 1, 0, y, 320, 198, dir_zona_pantalla); + for (int lang = 0; lang < _numLangs; lang++) { + entryLen = in.readUint16BE(); - if (sentido == 0) - y++; - else - y--; + res[lang] = (char **)malloc(sizeof(char *) * numTexts); - if (num_ejec == 3) { - if (y == 1) - sentido = 1; - if (y == -1) - sentido = 0; - } else { - if (y == 2) - sentido = 1; - if (y == 0) - sentido = 0; - } - if (contador > 0) - goto comienza; + pos = (char *)malloc(entryLen); + res[lang][0] = pos; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} + in.read(res[lang][0], entryLen); -void DrasculaEngine::abre_puerta(int nflag, int n_puerta) { - if (flags[nflag] == 0) { - if (num_ejec == 1 /*|| num_ejec == 4*/) { - if (nflag != 7) { - comienza_sound("s3.als"); - flags[nflag] = 1; - } - } else { - comienza_sound("s3.als"); - flags[nflag] = 1; - } + pos += DATAALIGNMENT; - if (n_puerta != NO_PUERTA) - puertas_cerradas(n_puerta); - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); - sin_verbo(); - } -} + for (int i = 1; i < numTexts; i++) { + pos -= 2; -void DrasculaEngine::mapa() { - int l, veo = 0; + len = READ_BE_UINT16(pos); + pos += 2 + len; - for (l = 0; l < objs_room; l++) { - if (x_raton > x1[l] && y_raton > y1[l] - && x_raton < x2[l] && y_raton < y2[l] - && visible[l] == 1) { - strcpy(texto_nombre, nombre_obj[l]); - hay_nombre = 1; - veo = 1; + res[lang][i] = pos; } } - if (veo == 0) - hay_nombre = 0; -} - -void DrasculaEngine::grr() { - int longitud; - longitud = 30; - - buffer_teclado(); - - color_abc(VERDE_OSCURO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open("s10.als"); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(4); - ctvd_speaker(1); - ctvd_output(sku); - } - - updateRoom(); - copyBackground(253, 110, 150, 65, 20, 30, dir_dibujo3, dir_zona_pantalla); - - if (con_voces == 0) - centra_texto(".groaaarrrrgghhh!", 153, 65); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - -bucless: - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::activa_pendulo() { - flags[1] = 2; - hare_se_ve = 0; - strcpy(num_room, "102.alg"); - loadPic("102.alg"); - decompressPic(dir_dibujo1, MEDIA); - loadPic("an_p1.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("an_p2.alg"); - decompressPic(dir_hare_dch, 1); - loadPic("an_p3.alg"); - decompressPic(dir_hare_frente, 1); - - copyBackground(0, 171, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3); - - conta_ciego_vez = vez(); + return res; } -void DrasculaEngine::cierra_puerta(int nflag, int n_puerta) { - if (flags[nflag] == 1) { - comienza_sound("s4.als"); - flags[nflag] = 0; - if (n_puerta != NO_PUERTA) - puertas_cerradas(n_puerta); - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); - sin_verbo(); +void DrasculaEngine::freeTexts(char ***ptr) { + for (int lang = 0; lang < _numLangs; lang++) { + free(ptr[lang][0] - DATAALIGNMENT); + free(ptr[lang]); } + free(ptr); } } // End of namespace Drascula diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index e1043561d3..ce67cc2c0e 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -35,6 +35,7 @@ #include "common/hash-str.h" #include "common/events.h" #include "common/keyboard.h" +#include "common/unarj.h" #include "sound/audiostream.h" #include "sound/mixer.h" @@ -45,290 +46,172 @@ namespace Drascula { +#define DRASCULA_DAT_VER 2 +#define DATAALIGNMENT 4 + enum DrasculaGameFeatures { + GF_PACKED = (1 << 0) +}; + +enum Languages { + kEnglish = 0, + kSpanish = 1, + kGerman = 2, + kFrench = 3, + kItalian = 4 +}; + +enum Verbs { + kVerbDefault = -1, + kVerbLook = 1, + kVerbPick = 2, + kVerbOpen = 3, + kVerbClose = 4, + kVerbTalk = 5, + kVerbMove = 6 +}; + +// Items up to chapter 3 +enum InventoryItems { + kItemMoney = 7, + kItemLeaves = 8, + kItemCross = 9, + kItemSpike = 10, + kItemEarplugs = 11, + kItemBook = 12, + kItemBubbleGum = 13, + kItemSickle = 14, + kItemTissues = 15, + kItemCigarettes = 16, + kItemCandle = 17, + kItemTwoCoins = 18, + kItemOneCoin = 19, + kItemReefer = 20, + kItemKey = 21, + kItemHandbag = 22, + kItemEarWithEarPlug = 23, + kItemPhone = 28 +}; + +// Items from chapter 4 onwards +enum InventoryItems2 { + kItemKey2 = 7, + kItemCross2 = 9, + kItemRope2 = 19, + kItemReefer2 = 20, + kItemOneCoin2 = 22, + kItemPhone2 = 28 +}; + +enum Colors { + kColorBrown = 1, + kColorDarkBlue = 2, + kColorLightGreen = 3, + kColorDarkGreen = 4, + kColorYellow = 5, + kColorOrange = 6, + kColorRed = 7, + kColorMaroon = 8, + kColorPurple = 9, + kColorWhite = 10, + kColorPink = 11 +}; + +enum SSNFrames { + kFrameInit = 0, + kFrameCmpRle = 1, + kFrameCmpOff = 2, + kFrameEndAnim = 3, + kFrameSetPal = 4, + kFrameMouseKey = 5, // unused + kFrameEmptyFrame = 6 +}; + +enum IgorTalkerTypes { + kIgorDch = 0, + kIgorFront = 1, + kIgorDoor = 2, + kIgorSeated = 3, + kIgorWig = 4 }; +enum AnimFrameTypes { + kFrameBlind = 0, + kFrameSnore = 1, + kFrameBat = 2, + kFrameVonBraun = 3, + kFramePianist = 4, + kFrameDrunk = 5, + kFrameCandles = 6, + kFramePendulum = 7 +}; + +#define TEXTD_START 68 + struct DrasculaGameDescription; -#define NUM_SAVES 10 -#define NUM_BANDERAS 50 -#define ESC 0x01 -#define F1 0x3B -#define F2 0x3C -#define F3 0x3D -#define F4 0x3E -#define F5 0x3F -#define F6 0x40 -#define F8 0x42 -#define F9 0x43 -#define F10 0x44 -#define LOOK 1 -#define PICK 2 -#define OPEN 3 -#define CLOSE 4 -#define TALK 5 -#define MOVE 6 -#define INICISOUND 6 -#define FINALSOUND 8 -#define FINDRV 9 -#define DIF_MASK 55 -#define ANCHOBJ 40 -#define ALTOBJ 25 - -#define X_OBJ1 5 -#define Y_OBJ1 10 -#define X_OBJ2 50 -#define Y_OBJ2 10 -#define X_OBJ3 95 -#define Y_OBJ3 10 -#define X_OBJ4 140 -#define Y_OBJ4 10 -#define X_OBJ5 185 -#define Y_OBJ5 10 -#define X_OBJ6 230 -#define Y_OBJ6 10 -#define X_OBJ7 275 -#define Y_OBJ7 10 -#define X_OBJ8 5 -#define Y_OBJ8 40 -#define X_OBJ9 50 -#define Y_OBJ9 40 -#define X_OBJ10 95 -#define Y_OBJ10 40 -#define X_OBJ11 140 -#define Y_OBJ11 40 -#define X_OBJ12 185 -#define Y_OBJ12 40 -#define X_OBJ13 230 -#define Y_OBJ13 40 -#define X_OBJ14 275 -#define Y_OBJ14 40 -#define X_OBJ15 5 -#define Y_OBJ15 70 -#define X_OBJ16 50 -#define Y_OBJ16 70 -#define X_OBJ17 95 -#define Y_OBJ17 70 -#define X_OBJ18 140 -#define Y_OBJ18 70 -#define X_OBJ19 185 -#define Y_OBJ19 70 -#define X_OBJ20 230 -#define Y_OBJ20 70 -#define X_OBJ21 275 -#define Y_OBJ21 70 -#define X_OBJ22 5 -#define Y_OBJ22 100 -#define X_OBJ23 50 -#define Y_OBJ23 100 -#define X_OBJ24 95 -#define Y_OBJ24 100 -#define X_OBJ25 140 -#define Y_OBJ25 100 -#define X_OBJ26 185 -#define Y_OBJ26 100 -#define X_OBJ27 230 -#define Y_OBJ27 100 -#define X_OBJ28 275 -#define Y_OBJ28 100 -#define X_OBJ29 5 -#define Y_OBJ29 130 -#define X_OBJ30 50 -#define Y_OBJ30 130 -#define X_OBJ31 95 -#define Y_OBJ31 130 -#define X_OBJ32 140 -#define Y_OBJ32 130 -#define X_OBJ33 185 -#define Y_OBJ33 130 -#define X_OBJ34 230 -#define Y_OBJ34 130 -#define X_OBJ35 275 -#define Y_OBJ35 130 -#define X_OBJ36 5 -#define Y_OBJ36 160 -#define X_OBJ37 50 -#define Y_OBJ37 160 -#define X_OBJ38 95 -#define Y_OBJ38 160 -#define X_OBJ39 140 -#define Y_OBJ39 160 -#define X_OBJ40 185 -#define Y_OBJ40 160 -#define X_OBJ41 230 -#define Y_OBJ41 160 -#define X_OBJ42 275 -#define Y_OBJ42 160 -#define X_OBJ43 275 -#define Y_OBJ43 160 - -#define DIF_MASK_HARE 72 -#define DIF_MASK_ABC 22 -#define ANCHO_LETRAS 8 -#define ALTO_LETRAS 6 - -#define Y_ABC 158 -#define Y_SIGNOS 169 -#define Y_ACENTOS 180 - -#define X_A 6 -#define X_B 15 -#define X_C 24 -#define X_D 33 -#define X_E 42 -#define X_F 51 -#define X_G 60 -#define X_H 69 -#define X_I 78 -#define X_J 87 -#define X_K 96 -#define X_L 105 -#define X_M 114 -#define X_N 123 -#define X_GN 132 -#define X_O 141 -#define X_P 150 -#define X_Q 159 -#define X_R 168 -#define X_S 177 -#define X_T 186 -#define X_U 195 -#define X_V 204 -#define X_W 213 -#define X_X 222 -#define X_Y 231 -#define X_Z 240 -#define X_PUNTO 6 -#define X_COMA 15 -#define X_GUION 24 -#define X_CIERRA_INTERROGACION 33 -#define X_ABRE_INTERROGACION 42 -#define X_COMILLAS 51 -#define X_CIERRA_EXCLAMACION 60 -#define X_ABRE_EXCLAMACION 69 -#define X_PUNTO_Y_COMA 78 -#define X_MAYOR_QUE 87 -#define X_MENOR_QUE 96 -#define X_DOLAR 105 -#define X_POR_CIENTO 114 -#define X_DOS_PUNTOS 123 -#define X_AND 132 -#define X_BARRA 141 -#define X_ABRE_PARENTESIS 150 -#define X_CIERRA_PARENTESIS 159 -#define X_ASTERISCO 168 -#define X_MAS 177 -#define X_N1 186 -#define X_N2 195 -#define X_N3 204 -#define X_N4 213 -#define X_N5 222 -#define X_N6 231 -#define X_N7 240 -#define X_N8 249 -#define X_N9 258 -#define X_N0 267 -#define ESPACIO 250 -#define ALTO_TALK_HARE 25 -#define ANCHO_TALK_HARE 23 -#define VON_BRAUN 1 -#define AZUL_OSCURO 2 -#define VERDE_CLARO 3 -#define VERDE_OSCURO 4 -#define AMARILLO 5 -#define NARANJA 6 -#define ROJO 7 -#define MARRON 8 -#define MORADO 9 -#define BLANCO 10 -#define ROSA 11 -#define PASO_HARE_X 8 -#define PASO_HARE_Y 3 -#define ALTO_PERSONAJE 70 -#define ANCHO_PERSONAJE 43 -#define PIES_HARE 12 - -#define ANCHO_LETRAS_OPC 6 -#define ALTO_LETRAS_OPC 5 -#define Y_ABC_OPC_1 6 -#define Y_SIGNOS_OPC_1 15 -#define Y_ABC_OPC_2 31 -#define Y_SIGNOS_OPC_2 40 -#define Y_ABC_OPC_3 56 -#define Y_SIGNOS_OPC_3 65 -#define X_A_OPC 10 -#define X_B_OPC 17 -#define X_C_OPC 24 -#define X_D_OPC 31 -#define X_E_OPC 38 -#define X_F_OPC 45 -#define X_G_OPC 52 -#define X_H_OPC 59 -#define X_I_OPC 66 -#define X_J_OPC 73 -#define X_K_OPC 80 -#define X_L_OPC 87 -#define X_M_OPC 94 -#define X_N_OPC 101 -#define X_GN_OPC 108 -#define X_O_OPC 115 -#define X_P_OPC 122 -#define X_Q_OPC 129 -#define X_R_OPC 136 -#define X_S_OPC 143 -#define X_T_OPC 150 -#define X_U_OPC 157 -#define X_V_OPC 164 -#define X_W_OPC 171 -#define X_X_OPC 178 -#define X_Y_OPC 185 -#define X_Z_OPC 192 -#define ESPACIO_OPC 199 -#define X_PUNTO_OPC 10 -#define X_COMA_OPC 17 -#define X_GUION_OPC 24 -#define X_CIERRA_INTERROGACION_OPC 31 -#define X_ABRE_INTERROGACION_OPC 38 -#define X_COMILLAS_OPC 45 -#define X_CIERRA_EXCLAMACION_OPC 52 -#define X_ABRE_EXCLAMACION_OPC 59 -#define X_PUNTO_Y_COMA_OPC 66 -#define X_MAYOR_QUE_OPC 73 -#define X_MENOR_QUE_OPC 80 -#define X_DOLAR_OPC 87 -#define X_POR_CIENTO_OPC 94 -#define X_DOS_PUNTOS_OPC 101 -#define X_AND_OPC 108 -#define X_BARRA_OPC 115 -#define X_ABRE_PARENTESIS_OPC 122 -#define X_CIERRA_PARENTESIS_OPC 129 -#define X_ASTERISCO_OPC 136 -#define X_MAS_OPC 143 -#define X_N1_OPC 150 -#define X_N2_OPC 157 -#define X_N3_OPC 164 -#define X_N4_OPC 171 -#define X_N5_OPC 178 -#define X_N6_OPC 185 -#define X_N7_OPC 192 -#define X_N8_OPC 199 -#define X_N9_OPC 206 -#define X_N0_OPC 213 -#define NO_PUERTA 99 - -#define INIT_FRAME 0 -#define CMP_RLE 1 -#define CMP_OFF 2 -#define END_ANIM 3 -#define SET_PALET 4 -#define MOUSE_KEY 5 -#define EMPTY_FRAME 6 - -#define COMPLETA 256 -#define MEDIA 128 +struct RoomTalkAction { + int room; + int chapter; + int action; + int objectID; + int speechID; +}; + +struct RoomUpdate { + int roomNum; + int flag; + int flagValue; + int sourceX; + int sourceY; + int destX; + int destY; + int width; + int height; + int type; // 0 - background, 1 - rect +}; + +struct ItemLocation { + int x; + int y; +}; + +struct CharInfo { + byte inChar; + uint16 mappedChar; + byte charType; // 0 - letters, 1 - signs, 2 - accented +}; + +#define NUM_SAVES 10 +#define NUM_FLAGS 50 +#define DIF_MASK 55 +#define OBJWIDTH 40 +#define OBJHEIGHT 25 + +#define DIF_MASK_HARE 72 +#define DIF_MASK_ABC 22 +#define CHAR_WIDTH 8 +#define CHAR_HEIGHT 6 + +#define TALK_HEIGHT 25 +#define TALK_WIDTH 23 +#define STEP_X 8 +#define STEP_Y 3 +#define CHARACTER_HEIGHT 70 +#define CHARACTER_WIDTH 43 +#define FEET_HEIGHT 12 + +#define CHAR_WIDTH_OPC 6 +#define CHAR_HEIGHT_OPC 5 +#define NO_DOOR 99 + +#define COMPLETE_PAL 256 +#define HALF_PAL 128 + +static const int interf_x[] ={ 1, 65, 129, 193, 1, 65, 129 }; +static const int interf_y[] ={ 51, 51, 51, 51, 83, 83, 83 }; class DrasculaEngine : public ::Engine { - int _gameId; Common::KeyState _keyPressed; protected: @@ -339,157 +222,337 @@ protected: public: DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gameDesc); virtual ~DrasculaEngine(); - int getGameId() { - return _gameId; - } Common::RandomSource *_rnd; const DrasculaGameDescription *_gameDescription; - uint32 getGameID() const; uint32 getFeatures() const; - uint16 getVersion() const; - Common::Platform getPlatform() const; - void update_events(); + Common::Language getLanguage() const; + void updateEvents(); + + void loadArchives(); Audio::SoundHandle _soundHandle; - void asigna_memoria(); - void libera_memoria(); - void salir_al_dos(int r); + void allocMemory(); + void freeMemory(); + void endChapter(); + + void loadPic(int roomNum, byte *targetSurface, int colorCount = 1) { + char rm[20]; + sprintf(rm, "%i.alg", roomNum); + loadPic(rm, targetSurface, colorCount); + } - void loadPic(const char *); - void decompressPic(byte *dir_escritura, int plt); + void loadPic(const char *NamePcc, byte *targetSurface, int colorCount = 1); typedef char DacPalette256[256][3]; - void asigna_rgb(byte *dir_lectura, int plt); - void funde_rgb(int plt); - void paleta_hare(); - void ActualizaPaleta(); - void setvgapalette256(byte *PalBuf); - void copyBackground(int xorg, int yorg, int xdes, int ydes, int Ancho, - int Alto, byte *Origen, byte *Destino); - void copyRect(int xorg, int yorg, int xdes, int ydes, int Ancho, - int Alto, byte *Origen, byte *Destino); - void copyRectClip(int *Array, byte *Origen, byte *Destino); - void updateScreen(int xorg, int yorg, int xdes, int ydes, int Ancho, int Alto, byte *Buffer); - - DacPalette256 palJuego; - DacPalette256 palHare; - DacPalette256 palHareClaro; - DacPalette256 palHareOscuro; + void setRGB(byte *pal, int plt); + void assignDefaultPalette(); + void setPalette(byte *PalBuf); + void copyBackground(int xorg, int yorg, int xdes, int ydes, int width, + int height, byte *src, byte *dest); + void copyRect(int xorg, int yorg, int xdes, int ydes, int width, + int height, byte *src, byte *dest); + void copyRectClip(int *Array, byte *src, byte *dest); + void updateScreen() { + updateScreen(0, 0, 0, 0, 320, 200, screenSurface); + } + void updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer); + int checkWrapX(int x) { + if (x < 0) x += 320; + if (x > 319) x -= 320; + return x; + } + int checkWrapY(int y) { + if (y < 0) y += 200; + if (y > 199) y -= 200; + return y; + } - byte *VGA; + DacPalette256 gamePalette; + DacPalette256 defaultPalette; + DacPalette256 brightPalette; + DacPalette256 darkPalette; - byte *dir_dibujo1; - byte *dir_hare_fondo; - byte *dir_dibujo3; - byte *dir_dibujo2; - byte *dir_mesa; - byte *dir_hare_dch; - byte *dir_zona_pantalla; - byte *dir_hare_frente; - byte *dir_texto; - byte *dir_pendulo; + // Graphics buffers/pointers + byte *VGA; + byte *bgSurface; + byte *backSurface; + byte *drawSurface3; + byte *drawSurface2; + byte *tableSurface; + byte *extraSurface; // not sure about this one, was "dir_hare_dch" + byte *screenSurface; + byte *frontSurface; + byte *textSurface; + byte *memPtr; + byte *mSession; byte cPal[768]; - byte *Buffer_pcx; - long LenFile; - - Common::File *ald, *sku; - - int hay_sb; - int nivel_osc, musica_antes, musica_room; - char num_room[20], roomDisk[20]; - char datos_actuales[20]; - int objs_room; - char fondo_y_menu[20]; - - char nombre_obj[30][20]; - char nombre_icono[44][13]; - - int num_obj[40], visible[40], espuerta[40]; - int sitiobj_x[40], sitiobj_y[40], sentidobj[40]; - int objetos_que_tengo[43]; - char alapantallakeva[40][20]; - int x_alakeva[40], y_alakeva[40], sentido_alkeva[40], alapuertakeva[40]; + + Common::ArjFile _arj; + + int actorFrames[8]; + + int previousMusic, roomMusic; + int roomNumber; + char roomDisk[20]; + char currentData[20]; + int numRoomObjs; + char menuBackground[20]; + + char objName[30][20]; + char iconName[44][13]; + + int objectNum[40], visible[40], isDoor[40]; + int roomObjX[40], roomObjY[40], trackObj[40]; + int inventoryObjects[43]; + char _targetSurface[40][20]; + int _destX[40], _destY[40], trackCharacter_alkeva[40], alapuertakeva[40]; int x1[40], y1[40], x2[40], y2[40]; - int lleva_objeto, objeto_que_lleva; - int con_voces; - int menu_bar, menu_scr, hay_nombre; - char texto_nombre[20]; - int frame_ciego; - int frame_ronquido; - int frame_murcielago; - int c_mirar; - int c_poder; - - int flags[NUM_BANDERAS]; + int takeObject, pickedObject; + int withVoices; + int menuBar, menuScreen, hasName; + char textName[20]; + int curExcuseLook; + int curExcuseAction; + + int flags[NUM_FLAGS]; int frame_y; - int hare_x, hare_y, hare_se_mueve, direccion_hare, sentido_hare, num_frame, hare_se_ve; - int sitio_x, sitio_y, comprueba_flags; - int rompo, rompo2; - int paso_x, paso_y; - int alto_hare, ancho_hare, alto_pies; - int alto_talk, ancho_talk; - int suelo_x1, suelo_y1, suelo_x2, suelo_y2; - int cerca, lejos; - int sentido_final, anda_a_objeto; - int obj_saliendo; - int diff_vez, conta_vez; - int hay_respuesta; - int conta_ciego_vez; - int cambio_de_color; - int rompo_y_salgo; - int vb_x, sentido_vb, vb_se_mueve, frame_vb; - float nuevo_alto, nuevo_ancho; - int diferencia_x, diferencia_y; + int curX, curY, characterMoved, curDirection, trackProtagonist, num_frame, hare_se_ve; + int roomX, roomY, checkFlags; + int doBreak; + int stepX, stepY; + int curHeight, curWidth, feetHeight; + int talkHeight, talkWidth; + int floorX1, floorY1, floorX2, floorY2; + int near, far; + int trackFinal, walkToObject; + int objExit; + int timeDiff, startTime; + int hasAnswer; + int savedTime; + int changeColor; + int breakOut; + int vonBraunX, trackVonBraun, vonBraunHasMoved; + float newHeight, newWidth; int factor_red[202]; - int frame_piano; - int frame_borracho; - int frame_velas; int color_solo; - int parpadeo; - int x_igor, y_igor, sentido_igor; - int x_dr, y_dr, sentido_dr; - int x_bj, y_bj, sentido_bj; - int cont_sv; + int blinking; + int igorX, igorY, trackIgor; + int drasculaX, drasculaY, trackDrascula; + int bjX, bjY, trackBJ; + int framesWithoutAction; int term_int; - int num_ejec; + int currentChapter; int hay_que_load; - char nom_partida[13]; + char saveName[13]; int _color; - int corta_musica; + int musicStopped; char select[23]; - int hay_seleccion; - int x_raton; - int y_raton; - int y_raton_ant; - int boton_izq; - int boton_dch; - - bool escoba(); - void Negro(); - void talk_vb(const char *, const char *); - void talk_vbpuerta(const char *dicho, const char *filename); - void talk_ciego(const char *, const char *, const char *); - void talk_hacker(const char *, const char *); - void agarra_objeto(int); - void anda_parriba(); - void anda_pabajo(); - void pon_vb(); - void lleva_vb(int punto_x); - void hipo_sin_nadie(int contador); - void abre_puerta(int nflag, int n_puerta); - void mapa(); - void buffer_teclado() { } + int selectionMade; + int mouseX; + int mouseY; + int leftMouseButton; + int rightMouseButton; + + bool loadDrasculaDat(); + + bool runCurrentChapter(); + void black(); + void pickObject(int); + void walkUp(); + void walkDown(); + void moveVonBraun(); + void placeVonBraun(int pointX); + void hipo_sin_nadie(int counter); + void openDoor(int nflag, int doorNum); + void showMap(); + + void setDarkPalette(); + + void withoutVerb(); + void enterRoom(int); + void clearRoom(); + void gotoObject(int, int); + void moveCursor(); + void checkObjects(); + void selectVerbFromBar(); + bool verify1(); + bool verify2(); + Common::KeyCode getScan(); + void selectVerb(int); + void updateVolume(Audio::Mixer::SoundType soundType, int prevVolume); + void volumeControls(); + bool saveLoadScreen(); + void print_abc(const char *, int, int); + void delay(int ms); + bool confirmExit(); + void screenSaver(); + void chooseObject(int object); + void addObject(int); + int removeObject(int osj); + void playFLI(const char *filefli, int vel); + void fadeFromBlack(int fadeSpeed); + void fadeToBlack(int fadeSpeed); + char adjustToVGA(char value); + void color_abc(int cl); + void centerText(const char *,int,int); + void playSound(int soundNum); + bool animate(const char *animation, int FPS); + void pause(int); + void placeIgor(); + void placeBJ(); + void placeDrascula(); + + void talkInit(const char *filename); + bool isTalkFinished(int* length); + void talk_igor(int, int); + void talk_drascula(int index, int talkerType = 0); + void talk_solo(const char *, const char *); + void talk_bartender(int, int talkerType = 0); + void talk_pen(const char *, const char *, int); + void talk_bj_bed(int); + void talk_htel(int); + void talk_bj(int); + void talk_baul(int); + void talk(int); + void talk(const char *, const char *); + void talk_sync(const char *, const char *, const char *); + void talk_drunk(int); + void talk_pianist(int); + void talk_werewolf(int); + void talk_mus(int); + void talk_dr_grande(int); + void talk_vonBraun(int); + void talk_vonBraunpuerta(int); + void talk_blind(int); + void talk_hacker(int); + void talk_generic(const char* said, const char* filename, int* faces, int faceCount, int* coords, byte* surface); + + void hiccup(int); + void finishSound(); + void stopSound(); + void closeDoor(int nflag, int doorNum); + void playMusic(int p); + void stopMusic(); + int musicStatus(); + void updateRoom(); + bool loadGame(const char *); + void updateDoor(int); + void setDefaultPalette(); + void setPaletteBase(int darkness); + void assignBrightPalette(); + void assignDarkPalette(); + void setBrightPalette(); + void updateVisible(); + void startWalking(); + void updateRefresh(); + void updateRefresh_pre(); + void moveCharacters(); + void showMenu(); + void clearMenu(); + void removeObject(); + bool exitRoom(int); + bool pickupObject(); + bool checkAction(int); + void setCursorTable(); + void enterName(); + bool soundIsActive(); + void waitFrameSSN(); + void mixVideo(byte *OldScreen, byte *NewScreen); + void decodeRLE(byte *BufferRLE, byte *MiVideoRLE); + void decodeOffset(byte *BufferOFF, byte *MiVideoOFF, int length); + byte *TryInMem(); + int playFrameSSN(); + + int UsingMem; + byte CHUNK; + byte CMP, dacSSN[768]; + int FrameSSN; + int globalSpeed; + uint32 LastFrame; + + int flag_tv; + + void showFrame(bool firstFrame = false); + int getTime(); + void reduce_hare_chico(int, int, int, int, int, int, int, byte *, byte *); + void quadrant_1(); + void quadrant_2(); + void quadrant_3(); + void quadrant_4(); + void saveGame(char[]); + void increaseFrameNum(); + int whichObject(); + bool checkMenuFlags(); + void setupRoomsTable(); + bool roomParse(int, int); + void converse(int); + void print_abc_opc(const char *, int, int, int); + void response(int); + void activatePendulum(); + + void MusicFadeout(); + void playFile(const char *fname); + + char *getLine(char *buf, int len); + void getIntFromLine(char *buf, int len, int* result); + void getStringFromLine(char *buf, int len, char* result); + + void grr(); + void updateAnim(int y, int destX, int destY, int width, int height, int count, byte* src, int delayVal = 3); + void updateAnim2(int y, int px, int py, int width, int height, int count, byte* src); + + bool room(int rN, int fl); + bool room_0(int); + bool room_1(int); + bool room_2(int); + bool room_3(int); + bool room_4(int); + bool room_5(int); + bool room_6(int); + bool room_7(int); + bool room_8(int); + bool room_9(int); + bool room_12(int); + bool room_13(int); + bool room_14(int); + bool room_15(int); + bool room_16(int); + bool room_17(int); + bool room_18(int); + bool room_21(int); + bool room_22(int); + bool room_23(int); + bool room_24(int); + bool room_26(int); + bool room_27(int); + bool room_29(int); + bool room_30(int); + bool room_31(int); + bool room_34(int); + bool room_35(int); + bool room_49(int); + bool room_53(int); + bool room_54(int); + bool room_55(int); + bool room_56(int); + bool room_58(int); + bool room_59(int); + bool room_60(int); + bool room_62(int); + bool room_102(int); + void animation_1_1(); void animation_2_1(); - void animation_1_2(); - void animation_2_2(); void animation_3_1(); void animation_4_1(); + // + void animation_1_2(); + void animation_2_2(); void animation_3_2(); void animation_4_2(); void animation_5_2(); @@ -511,8 +574,8 @@ public: void animation_21_2(); void animation_22_2(); void animation_23_2(); - void animation_23_anexo(); - void animation_23_anexo2(); + void animation_23_joined(); + void animation_23_joined2(); void animation_24_2(); void animation_25_2(); void animation_26_2(); @@ -526,225 +589,15 @@ public: void animation_34_2(); void animation_35_2(); void animation_36_2(); - - void update_1_pre(); - void update_2(); - void update_3(); - void update_3_pre(); - void update_4(); - void update_5(); - void update_5_pre(); - void update_6_pre(); - void update_7_pre(); - void update_9_pre(); - void update_12_pre(); - void update_14_pre(); - void update_15(); - void update_16_pre(); - void update_17_pre(); - void update_17(); - void update_18_pre(); - void update_18(); - void update_21_pre(); - void update_22_pre(); - void update_23_pre(); - void update_24_pre(); - void update_26_pre(); - void update_26(); - void update_27(); - void update_27_pre(); - void update_29(); - void update_29_pre(); - void update_30_pre(); - void update_31_pre(); - void update_34_pre(); - void update_35_pre(); - void update_31(); - void update_34(); - void update_35(); - void hare_oscuro(); - - - void sin_verbo(); - bool para_cargar(char[]); - void carga_escoba(const char *); - void clearRoom(); - void lleva_al_hare(int, int); - void mueve_cursor(); - void comprueba_objetos(); - void espera_soltar(); - void MirarRaton(); - void elige_en_barra(); - bool comprueba1(); - bool comprueba2(); - Common::KeyCode getscan(); - void elige_verbo(int); - void mesa(); - bool saves(); - void print_abc(const char *, int, int); - void delay(int ms); - bool confirma_salir(); - void salva_pantallas(); - void elige_objeto(int objeto); - void suma_objeto(int); - int resta_objeto(int osj); - void fliplay(const char *filefli, int vel); - void FundeDelNegro(int VelocidadDeFundido); - char LimitaVGA(char valor); - void color_abc(int cl); - void centra_texto(const char *,int,int); - void comienza_sound(const char *); - void anima(const char *animation, int FPS); - void fin_sound_corte(); - void FundeAlNegro(int VelocidadDeFundido); - void pause(int); - void talk_dr_grande(const char *dicho, const char *filename); - void pon_igor(); - void pon_bj(); - void pon_dr(); - void talk_igor_dch(const char *dicho, const char *filename); - void talk_dr_dch(const char *dicho, const char *filename); - void talk_dr_izq(const char *dicho, const char *filename); - void talk_solo(const char *, const char *); - void talk_igor_frente(const char *, const char *); - void talk_tabernero(const char *dicho, const char *filename); - void talk_igorpuerta(const char *dicho, const char *filename); - void talk_igor_peluca(const char *dicho, const char *filename); - void hipo(int); - void fin_sound(); - void talk_bj(const char *, const char *); - void talk_baul(const char *dicho, const char *filename); - void talk(const char *, const char *); - void talk_sinc(const char *, const char *, const char *); - void cierra_puerta(int nflag, int n_puerta); - void playmusic(int p); - void stopmusic(); - int music_status(); - void updateRoom(); - bool carga_partida(const char *); - void puertas_cerradas(int); - void animafin_sound_corte(); - void color_hare(); - void funde_hare(int oscuridad); - void paleta_hare_claro(); - void paleta_hare_oscuro(); - void hare_claro(); - void actualiza_datos(); - void empieza_andar(); - void updateRefresh(); - void updateRefresh_pre(); - void pon_hare(); - void menu_sin_volcar(); - void barra_menu(); - void saca_objeto(); - bool sal_de_la_habitacion(int); - bool coge_objeto(); - bool banderas(int); - void cursor_mesa(); - void introduce_nombre(); - void para_grabar(char[]); - int LookForFree(); - void OpenSSN(const char *Name, int Pause); - void WaitFrameSSN(); - void MixVideo(byte *OldScreen, byte *NewScreen); - void Des_RLE(byte *BufferRLE, byte *MiVideoRLE); - void Des_OFF(byte *BufferOFF, byte *MiVideoOFF, int Lenght); - void set_dacSSN(byte *dacSSN); - byte *TryInMem(Common::File *Sesion); - void EndSSN(); - int PlayFrameSSN(); - - byte *AuxBuffOrg; - byte *AuxBuffLast; - byte *AuxBuffDes; - int Leng; - - byte *pointer; - int UsingMem; - Common::File *_Sesion; - byte CHUNK; - byte CMP, dacSSN[768]; - byte *MiVideoSSN; - byte *mSesion; - int FrameSSN; - int GlobalSpeed; - uint32 LastFrame; - - int frame_pen; - int flag_tv; - - byte *carga_pcx(byte *NamePcc); - void set_dac(byte *dac); - void WaitForNext(int FPS); - int vez(); - void reduce_hare_chico(int, int, int, int, int, int, int, byte *, byte *); - char codifica(char); - void cuadrante_1(); - void cuadrante_2(); - void cuadrante_3(); - void cuadrante_4(); - void update_62(); - void update_62_pre(); - void update_63(); - void graba_partida(char[]); - void aumenta_num_frame(); - int sobre_que_objeto(); - bool comprueba_banderas_menu(); - void room_0(); - void room_1(int); - void room_2(int); - void room_3(int); - void room_4(int); - void room_5(int); - void room_6(int); - void room_7(int); - void room_8(int); - void room_9(int); - void room_12(int); - void room_14(int); - void room_15(int); - void room_16(int); - void room_17(int); - void room_18(int); - void room_19(int); - bool room_21(int); - void room_22(int); - void room_23(int); - void room_24(int); - void room_26(int); - void room_27(int); - void room_29(int); - void room_30(int); - void room_31(int); - void room_34(int); - void room_35(int); - void room_44(int); - void room_62(int); - void room_63(int); - void conversa(const char *); - void print_abc_opc(const char *, int, int, int); - void responde(int); - void talk_borracho(const char *dicho, const char *filename); - void talk_pianista(const char *dicho, const char *filename); - - void MusicFadeout(); - void ctvd_end(); - void ctvd_stop(); - void ctvd_terminate(); - void ctvd_speaker(int flag); - void ctvd_output(Common::File *file_handle); - void ctvd_init(int b); - void grr(); - bool room_13(int fl); - void update_13(); - void update_20(); + // void animation_1_3(); void animation_2_3(); void animation_3_3(); void animation_4_3(); void animation_5_3(); void animation_6_3(); - void animation_rayo(); + void animation_ray(); + // void animation_1_4(); void animation_2_4(); void animation_3_4(); @@ -754,6 +607,7 @@ public: void animation_7_4(); void animation_8_4(); void animation_9_4(); + // void animation_1_5(); void animation_2_5(); void animation_3_5(); @@ -771,32 +625,7 @@ public: void animation_15_5(); void animation_16_5(); void animation_17_5(); - void room_49(int); - void room_53(int); - void room_54(int); - void room_55(int); - bool room_56(int); - void update_53_pre(); - void update_54_pre(); - void update_49_pre(); - void update_56_pre(); - void update_50(); - void update_57(); - void talk_igor_sentado(const char *, const char *); - void talk_lobo(const char *dicho, const char *filename); - void talk_mus(const char *dicho, const char *filename); - void room_58(int); - void room_59(int); - bool room_60(int); - void room_61(int); - void room_pendulo(int); - void update_pendulo(); - void update_58(); - void update_58_pre(); - void update_59_pre(); - void update_60_pre(); - void update_60(); - void update_61(); + // void animation_1_6(); void animation_2_6(); void animation_3_6(); @@ -813,29 +642,77 @@ public: void animation_15_6(); void animation_18_6(); void animation_19_6(); - void activa_pendulo(); - void talk_pen(const char *, const char *); - void talk_pen2(const char *, const char *); - void talk_taber2(const char *, const char *); - void talk_bj_cama(const char *dicho, const char * filename); - void talk_htel(const char *dicho, const char *filename); + + void update_1_pre(); + void update_2(); + void update_3(); + void update_4(); + void update_6_pre(); + void update_9_pre(); + void update_14_pre(); + void update_13(); + void update_16_pre(); + void update_18_pre(); + void update_23_pre(); + void update_26_pre(); + void update_26(); + void update_35_pre(); + void update_58(); + void update_58_pre(); + void update_59_pre(); + void update_60_pre(); + void update_60(); + void update_62(); + void update_62_pre(); + void update_102(); private: int _lang; -}; -extern const char *_text[][501]; -extern const char *_textd[][79]; -extern const char *_textb[][15]; -extern const char *_textbj[][29]; -extern const char *_texte[][24]; -extern const char *_texti[][33]; -extern const char *_textl[][32]; -extern const char *_textp[][20]; -extern const char *_textt[][25]; -extern const char *_textvb[][63]; -extern const char *_textsys[][4]; -extern const char *_texthis[][5]; + CharInfo *_charMap; + int _charMapSize; + + int _itemLocationsSize; + int _polXSize; + int _verbBarXSize; + int _x1dMenuSize; + int _frameXSize; + int _candleXSize; + int _pianistXSize; + int _drunkXSize; + int _roomPreUpdatesSize; + int _roomUpdatesSize; + int _roomActionsSize; + int _numLangs; + + char ***_text; + char ***_textd; + char ***_textb; + char ***_textbj; + char ***_texte; + char ***_texti; + char ***_textl; + char ***_textp; + char ***_textt; + char ***_textvb; + char ***_textsys; + char ***_texthis; + char ***_textverbs; + char ***_textmisc; + char ***_textd1; + ItemLocation *_itemLocations; + int *_polX, *_polY; + int *_verbBarX; + int *_x1d_menu, *_y1d_menu; + int *_frameX; + int *_candleX, *_candleY; + int *_pianistX, *_drunkX; + RoomUpdate *_roomPreUpdates, *_roomUpdates; + RoomTalkAction *_roomActions; + + char ***loadTexts(Common::File &in); + void freeTexts(char ***ptr); +}; } // End of namespace Drascula diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp new file mode 100644 index 0000000000..64591a856e --- /dev/null +++ b/engines/drascula/graphics.cpp @@ -0,0 +1,687 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::allocMemory() { + // FIXME: decodeOffset writes beyond 64000, so this + // buffer has been initialized to 64256 bytes (like + // the original did with the MiVideoSSN buffer) + screenSurface = (byte *)malloc(64256); + assert(screenSurface); + frontSurface = (byte *)malloc(64000); + assert(frontSurface); + backSurface = (byte *)malloc(64000); + assert(backSurface); + bgSurface = (byte *)malloc(64000); + assert(bgSurface); + drawSurface2 = (byte *)malloc(64000); + assert(drawSurface2); + drawSurface3 = (byte *)malloc(64000); + assert(drawSurface3); + tableSurface = (byte *)malloc(64000); + assert(tableSurface); + extraSurface = (byte *)malloc(64000); + assert(extraSurface); +} + +void DrasculaEngine::freeMemory() { + free(screenSurface); + free(bgSurface); + free(backSurface); + free(drawSurface2); + free(tableSurface); + free(drawSurface3); + free(extraSurface); + free(frontSurface); +} + +void DrasculaEngine::moveCursor() { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + + updateRefresh_pre(); + moveCharacters(); + updateRefresh(); + + if (!strcmp(textName, "hacker") && hasName == 1) { + if (_color != kColorRed && menuScreen == 0) + color_abc(kColorRed); + } else if (menuScreen == 0 && _color != kColorLightGreen) + color_abc(kColorLightGreen); + if (hasName == 1 && menuScreen == 0) + centerText(textName, mouseX, mouseY); + if (menuScreen == 1) + showMenu(); + else if (menuBar == 1) + clearMenu(); + + int cursorPos[6] = { 0, 0, mouseX - 20, mouseY - 17, OBJWIDTH, OBJHEIGHT }; + copyRectClip(cursorPos, drawSurface3, screenSurface); +} + +void DrasculaEngine::setCursorTable() { + int cursorPos[6] = { 225, 56, mouseX - 20, mouseY - 12, 40, 25 }; + copyRectClip(cursorPos, tableSurface, screenSurface); +} + +void DrasculaEngine::loadPic(const char *NamePcc, byte *targetSurface, int colorCount) { + unsigned int con, x = 0; + unsigned int fExit = 0; + byte ch, rep; + + _arj.open(NamePcc); + if (!_arj.isOpen()) + error("missing game data %s %c", NamePcc, 7); + + _arj.seek(128); + while (!fExit) { + ch = _arj.readByte(); + rep = 1; + if ((ch & 192) == 192) { + rep = (ch & 63); + ch = _arj.readByte(); + } + for (con = 0; con < rep; con++) { + x++; + if (x > 64000) { + fExit = 1; + break; + } + *targetSurface++ = ch; + } + } + + for (int i = 0; i < 256; i++) { + cPal[i * 3 + 0] = _arj.readByte(); + cPal[i * 3 + 1] = _arj.readByte(); + cPal[i * 3 + 2] = _arj.readByte(); + } + + _arj.close(); + + setRGB((byte *)cPal, colorCount); +} + +void DrasculaEngine::showFrame(bool firstFrame) { + int dataSize = _arj.readSint32LE(); + byte *pcxData = (byte *)malloc(dataSize); + _arj.read(pcxData, dataSize); + + for (int i = 0; i < 256; i++) { + cPal[i * 3 + 0] = _arj.readByte(); + cPal[i * 3 + 1] = _arj.readByte(); + cPal[i * 3 + 2] = _arj.readByte(); + } + + byte *prevFrame = (byte *)malloc(64000); + memcpy(prevFrame, VGA, 64000); + + decodeRLE(pcxData, VGA); + + free(pcxData); + + if (!firstFrame) + mixVideo(VGA, prevFrame); + + _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); + _system->updateScreen(); + if (firstFrame) + setPalette(cPal); + + free(prevFrame); +} + +void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, + int height, byte *src, byte *dest) { + dest += xdes + ydes * 320; + src += xorg + yorg * 320; + for (int x = 0; x < height; x++) { + memcpy(dest, src, width); + dest += 320; + src += 320; + } +} + +void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width, + int height, byte *src, byte *dest) { + int y, x; + + dest += xdes + ydes * 320; + src += xorg + yorg * 320; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + if (src[x + y * 320] != 255) + dest[x + y * 320] = src[x + y * 320]; +} + +void DrasculaEngine::copyRectClip(int *Array, byte *src, byte *dest) { + int y, x; + int xorg = Array[0]; + int yorg = Array[1]; + int xdes = Array[2]; + int ydes = Array[3]; + int width = Array[4]; + int height = Array[5]; + + if (ydes < 0) { + yorg += -ydes; + height += ydes; + ydes = 0; + } + if (xdes < 0) { + xorg += -xdes; + width += xdes; + xdes = 0; + } + if ((xdes + width) > 319) + width -= (xdes + width) - 320; + if ((ydes + height) > 199) + height -= (ydes + height) - 200; + + dest += xdes + ydes * 320; + src += xorg + yorg * 320; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + if (src[x + y * 320] != 255) + dest[x + y * 320] = src[x + y * 320]; +} + +void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) { + byte *ptr = VGA; + + ptr += xdes + ydes * 320; + buffer += xorg + yorg * 320; + for (int x = 0; x < height; x++) { + memcpy(ptr, buffer, width); + ptr += 320; + buffer += 320; + } + + _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); + _system->updateScreen(); +} + +void DrasculaEngine::print_abc(const char *said, int screenX, int screenY) { + int letterY = 0, letterX = 0, i; + uint len = strlen(said); + byte c; + + for (uint h = 0; h < len; h++) { + c = toupper(said[h]); + + for (i = 0; i < _charMapSize; i++) { + if (c == _charMap[i].inChar) { + letterX = _charMap[i].mappedChar; + + switch (_charMap[i].charType) { + case 0: // letters + letterY = (_lang == kSpanish) ? 149 : 158; + break; + case 1: // signs + letterY = (_lang == kSpanish) ? 160 : 169; + break; + case 2: // accented + letterY = 180; + break; + } // switch + break; + } // if + } // for + + int textPos[6] = { letterX, letterY, screenX, screenY, CHAR_WIDTH, CHAR_HEIGHT }; + copyRectClip(textPos, textSurface, screenSurface); + + screenX = screenX + CHAR_WIDTH; + if (screenX > 317) { + screenX = 0; + screenY = screenY + CHAR_HEIGHT + 2; + } + } // for +} + +void DrasculaEngine::print_abc_opc(const char *said, int screenX, int screenY, int game) { + int signY, letterY, letterX = 0; + uint len = strlen(said); + + for (uint h = 0; h < len; h++) { + if (game == 1) { + letterY = 6; + signY = 15; + } else if (game == 3) { + letterY = 56; + signY = 65; + } else { + letterY = 31; + signY = 40; + } + + byte c = toupper(said[h]); + + // WORKAROUND: Even original did not process it correctly + // Fixes apostrophe rendering + if (_lang != kSpanish) + if (c == '\'') + c = (byte)'\244'; + + for (int i = 0; i < _charMapSize; i++) { + if (c == _charMap[i].inChar) { + // Convert the mapped char of the normal font to the + // mapped char of the dialogue font + + int multiplier = (_charMap[i].mappedChar - 6) / 9; + + letterX = multiplier * 7 + 10; + + if (_charMap[i].charType > 0) + letterY = signY; + break; + } // if + } // for + + int textPos[6] = { letterX, letterY, screenX, screenY, CHAR_WIDTH_OPC, CHAR_HEIGHT_OPC }; + copyRectClip(textPos, backSurface, screenSurface); + + screenX = screenX + CHAR_WIDTH_OPC; + } +} + +void DrasculaEngine::centerText(const char *message, int textX, int textY) { + char bb[200], m2[200], m1[200], mb[10][50]; + char m3[200]; + int h, fil, textX3, textX2, textX1, conta_f = 0, ya = 0; + + strcpy(m1, " "); + strcpy(m2, " "); + strcpy(m3, " "); + strcpy(bb, " "); + + for (h = 0; h < 10; h++) + strcpy(mb[h], " "); + + if (textX > 160) + ya = 1; + + strcpy(m1, message); + textX = CLIP<int>(textX, 60, 255); + + textX1 = textX; + + if (ya == 1) + textX1 = 315 - textX; + + textX2 = (strlen(m1) / 2) * CHAR_WIDTH; + + while (true) { + strcpy(bb, m1); + scumm_strrev(bb); + + if (textX1 < textX2) { + strcpy(m3, strrchr(m1, ' ')); + strcpy(m1, strstr(bb, " ")); + scumm_strrev(m1); + m1[strlen(m1) - 1] = '\0'; + strcat(m3, m2); + strcpy(m2, m3); + }; + + textX2 = (strlen(m1) / 2) * CHAR_WIDTH; + + if (textX1 < textX2) + continue; + + strcpy(mb[conta_f], m1); + + if (!strcmp(m2, "")) + break; + + scumm_strrev(m2); + m2[strlen(m2) - 1] = '\0'; + scumm_strrev(m2); + strcpy(m1, m2); + strcpy(m2, ""); + conta_f++; + } + + fil = textY - (((conta_f + 3) * CHAR_HEIGHT)); + + for (h = 0; h < conta_f + 1; h++) { + textX3 = strlen(mb[h]) / 2; + print_abc(mb[h], ((textX) - textX3 * CHAR_WIDTH) - 1, fil); + fil = fil + CHAR_HEIGHT + 2; + } +} + +void DrasculaEngine::screenSaver() { + int xr, yr; + byte *copia, *ghost; + float coeff = 0, coeff2 = 0; + int count = 0; + int count2 = 0; + int tempLine[320]; + int tempRow[200]; + + clearRoom(); + + loadPic("sv.alg", bgSurface, HALF_PAL); + + // inicio_ghost(); + copia = (byte *)malloc(64000); + ghost = (byte *)malloc(65536); + + // carga_ghost(); + _arj.open("ghost.drv"); + if (!_arj.isOpen()) + error("Cannot open file ghost.drv"); + + _arj.read(ghost, 65536); + _arj.close(); + + updateEvents(); + xr = mouseX; + yr = mouseY; + + for (;;) { + // efecto(bgSurface); + + memcpy(copia, bgSurface, 64000); + coeff += 0.1f; + coeff2 = coeff; + + if (++count > 319) + count = 0; + + for (int i = 0; i < 320; i++) { + tempLine[i] = (int)(sin(coeff2) * 16); + coeff2 += 0.02f; + tempLine[i] = checkWrapY(tempLine[i]); + } + + coeff2 = coeff; + for (int i = 0; i < 200; i++) { + tempRow[i] = (int)(sin(coeff2) * 16); + coeff2 += 0.02f; + tempRow[i] = checkWrapX(tempRow[i]); + } + + if (++count2 > 199) + count2 = 0; + + int x1_, y1_, off1, off2; + + for (int i = 0; i < 200; i++) { + for (int j = 0; j < 320; j++) { + x1_ = j + tempRow[i]; + x1_ = checkWrapX(x1_); + + y1_ = i + count2; + y1_ = checkWrapY(y1_); + + off1 = 320 * y1_ + x1_; + + x1_ = j + count; + x1_ = checkWrapX(x1_); + + y1_ = i + tempLine[j]; + y1_ = checkWrapY(y1_); + off2 = 320 * y1_ + x1_; + + VGA[320 * i + j] = ghost[bgSurface[off2] + (copia[off1] << 8)]; + } + } + _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); + _system->updateScreen(); + + _system->delayMillis(20); + + // end of efecto() + + updateEvents(); + if (rightMouseButton == 1 || leftMouseButton == 1) + break; + if (mouseX != xr) + break; + if (mouseY != yr) + break; + } + // fin_ghost(); + free(copia); + free(ghost); + + loadPic(roomNumber, bgSurface, HALF_PAL); +} + +void DrasculaEngine::playFLI(const char *filefli, int vel) { + // Open file + globalSpeed = 1000 / vel; + FrameSSN = 0; + UsingMem = 0; + _arj.open(filefli); + mSession = TryInMem(); + LastFrame = _system->getMillis(); + + while (playFrameSSN() && (!term_int)) { + if (getScan() == Common::KEYCODE_ESCAPE) + term_int = 1; + } + + if (UsingMem) + free(memPtr); + else + _arj.close(); +} + +int DrasculaEngine::playFrameSSN() { + int Exit = 0; + uint32 length; + byte *BufferSSN; + + if (!UsingMem) + CHUNK = _arj.readByte(); + else { + memcpy(&CHUNK, mSession, 1); + mSession += 1; + } + + switch (CHUNK) { + case kFrameSetPal: + if (!UsingMem) { + for (int i = 0; i < 256; i++) { + dacSSN[i * 3 + 0] = _arj.readByte(); + dacSSN[i * 3 + 1] = _arj.readByte(); + dacSSN[i * 3 + 2] = _arj.readByte(); + } + } else { + memcpy(dacSSN, mSession, 768); + mSession += 768; + } + setPalette(dacSSN); + break; + case kFrameEmptyFrame: + waitFrameSSN(); + break; + case kFrameInit: + if (!UsingMem) { + CMP = _arj.readByte(); + length = _arj.readUint32LE(); + } else { + memcpy(&CMP, mSession, 1); + mSession += 1; + length = READ_LE_UINT32(mSession); + mSession += 4; + } + if (CMP == kFrameCmpRle) { + BufferSSN = (byte *)malloc(length); + if (!UsingMem) { + _arj.read(BufferSSN, length); + } else { + memcpy(BufferSSN, mSession, length); + mSession += length; + } + decodeRLE(BufferSSN, screenSurface); + free(BufferSSN); + waitFrameSSN(); + if (FrameSSN) + mixVideo(VGA, screenSurface); + else + memcpy(VGA, screenSurface, 64000); + _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); + _system->updateScreen(); + FrameSSN++; + } else { + if (CMP == kFrameCmpOff) { + BufferSSN = (byte *)malloc(length); + if (!UsingMem) { + _arj.read(BufferSSN, length); + } else { + memcpy(BufferSSN, mSession, length); + mSession += length; + } + decodeOffset(BufferSSN, screenSurface, length); + free(BufferSSN); + waitFrameSSN(); + if (FrameSSN) + mixVideo(VGA, screenSurface); + else + memcpy(VGA, screenSurface, 64000); + _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); + _system->updateScreen(); + FrameSSN++; + } + } + break; + case kFrameEndAnim: + Exit = 1; + break; + default: + Exit = 1; + break; + } + + return (!Exit); +} + +byte *DrasculaEngine::TryInMem() { + int length; + + _arj.seek(0, SEEK_END); + length = _arj.pos(); + _arj.seek(0, SEEK_SET); + memPtr = (byte *)malloc(length); + if (memPtr == NULL) + return NULL; + _arj.read(memPtr, length); + UsingMem = 1; + _arj.close(); + + return memPtr; +} + +void DrasculaEngine::decodeOffset(byte *BufferOFF, byte *MiVideoOFF, int length) { + int x = 0; + int size; + int offset; + + memset(screenSurface, 0, 64000); + while (x < length) { + offset = BufferOFF[x] + BufferOFF[x + 1] * 256; + // FIXME: this writes beyond 64000, so the buffer has been initialized + // to 64256 bytes (like the original did) + size = BufferOFF[x + 2]; + memcpy(MiVideoOFF + offset, &BufferOFF[x + 3], size); + x += 3 + size; + } +} + +void DrasculaEngine::decodeRLE(byte* srcPtr, byte* dstPtr) { + bool stopProcessing = false; + byte pixel; + uint repeat; + int curByte = 0; + + while (!stopProcessing) { + pixel = *srcPtr++; + repeat = 1; + if ((pixel & 192) == 192) { + repeat = (pixel & 63); + pixel = *srcPtr++; + } + for (uint j = 0; j < repeat; j++) { + curByte++; + if (curByte > 64000) { + stopProcessing = true; + break; + } + *dstPtr++ = pixel; + } + } +} + +void DrasculaEngine::mixVideo(byte *OldScreen, byte *NewScreen) { + for (int x = 0; x < 64000; x++) + OldScreen[x] ^= NewScreen[x]; +} + +void DrasculaEngine::waitFrameSSN() { + uint32 now; + while ((now = _system->getMillis()) - LastFrame < ((uint32) globalSpeed)) + _system->delayMillis(globalSpeed - (now - LastFrame)); + LastFrame = LastFrame + globalSpeed; +} + +bool DrasculaEngine::animate(const char *animationFile, int FPS) { + int NFrames = 1; + int cnt = 2; + + _arj.open(animationFile); + + if (!_arj.isOpen()) { + error("Animation file %s not found", animationFile); + } + + NFrames = _arj.readSint32LE(); + showFrame(true); + _system->delayMillis(1000 / FPS); + while (cnt < NFrames) { + showFrame(); + _system->delayMillis(1000 / FPS); + cnt++; + byte key = getScan(); + if (key == Common::KEYCODE_ESCAPE) + term_int = 1; + if (key != 0) + break; + } + _arj.close(); + + return ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)); +} + + + +} // End of namespace Drascula diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp new file mode 100644 index 0000000000..6e86788007 --- /dev/null +++ b/engines/drascula/interface.cpp @@ -0,0 +1,209 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::selectVerbFromBar() { + for (int n = 0; n < 7; n++) { + if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1] && n > 0) { + selectVerb(n); + return; + } + } + + // no verb selected + withoutVerb(); +} + +void DrasculaEngine::selectVerb(int verb) { + int c = (menuScreen == 1) ? 0 : 171; + + if (currentChapter == 5) { + if (takeObject == 1 && pickedObject != 16) + addObject(pickedObject); + } else { + if (takeObject == 1) + addObject(pickedObject); + } + + copyBackground(OBJWIDTH * verb, c, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3); + + takeObject = 1; + pickedObject = verb; +} + +bool DrasculaEngine::confirmExit() { + byte key; + + color_abc(kColorRed); + updateRoom(); + centerText(_textsys[_lang][1], 160, 87); + updateScreen(); + + delay(100); + for (;;) { + key = getScan(); + if (key != 0) + break; + } + + if (key == Common::KEYCODE_ESCAPE) { + stopMusic(); + return false; + } + + return true; +} + +void DrasculaEngine::showMenu() { + int h, n, x; + char textIcon[13]; + byte *srcSurface = (currentChapter == 6) ? tableSurface : frontSurface; + x = whichObject(); + strcpy(textIcon, iconName[x]); + + for (n = 1; n < 43; n++) { + h = inventoryObjects[n]; + + if (h != 0) { + copyBackground(_polX[n], _polY[n], _itemLocations[n].x, _itemLocations[n].y, + OBJWIDTH, OBJHEIGHT, srcSurface, screenSurface); + } + copyRect(_x1d_menu[h], _y1d_menu[h], _itemLocations[n].x, _itemLocations[n].y, + OBJWIDTH, OBJHEIGHT, backSurface, screenSurface); + } + + if (x < 7) + print_abc(textIcon, _itemLocations[x].x - 2, _itemLocations[x].y - 7); +} + +void DrasculaEngine::clearMenu() { + int n, verbActivated = 1; + + for (n = 0; n < 7; n++) { + if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1]) + verbActivated = 0; + copyRect(OBJWIDTH * n, OBJHEIGHT * verbActivated, _verbBarX[n], 2, + OBJWIDTH, OBJHEIGHT, backSurface, screenSurface); + verbActivated = 1; + } +} + +void DrasculaEngine::enterName() { + Common::KeyCode key; + int v = 0, h = 0; + char select2[23]; + strcpy(select2, " "); + for (;;) { + select2[v] = '-'; + copyBackground(115, 14, 115, 14, 176, 9, bgSurface, screenSurface); + print_abc(select2, 117, 15); + updateScreen(); + key = getScan(); + delay(70); + if (key != 0) { + if (key >= 0 && key <= 0xFF && isalpha(key)) + select2[v] = tolower(key); + else if ((key == Common::KEYCODE_LCTRL) || (key == Common::KEYCODE_RCTRL)) + select2[v] = '\164'; + else if (key >= Common::KEYCODE_0 && key <= Common::KEYCODE_9) + select2[v] = key; + else if (key == Common::KEYCODE_SPACE) + select2[v] = '\167'; + else if (key == Common::KEYCODE_ESCAPE) + break; + else if (key == Common::KEYCODE_RETURN) { + select2[v] = '\0'; + h = 1; + break; + } else if (key == Common::KEYCODE_BACKSPACE) + select2[v] = '\0'; + else + v--; + + if (key == Common::KEYCODE_BACKSPACE) + v--; + else + v++; + } + if (v == 22) + v = 21; + else if (v == -1) + v = 0; + } + if (h == 1) { + strcpy(select, select2); + selectionMade = 1; + } +} + +bool DrasculaEngine::checkMenuFlags() { + for (int n = 0; n < 43; n++) { + if (whichObject() == n) { + if (inventoryObjects[n] != 0 && checkAction(inventoryObjects[n])) + return true; + } + } + + return false; +} + +void DrasculaEngine::showMap() { + hasName = 0; + + for (int l = 0; l < numRoomObjs; l++) { + if (mouseX > x1[l] && mouseY > y1[l] + && mouseX < x2[l] && mouseY < y2[l] + && visible[l] == 1) { + strcpy(textName, objName[l]); + hasName = 1; + } + } +} + +void DrasculaEngine::grr() { + int length = 30; + + color_abc(kColorDarkGreen); + + playFile("s10.als"); + + updateRoom(); + copyBackground(253, 110, 150, 65, 20, 30, drawSurface3, screenSurface); + + if (withVoices == 0) + centerText("groaaarrrrgghhhh!", 153, 65); + + updateScreen(); + + while (!isTalkFinished(&length)); + + updateRoom(); + updateScreen(); +} + +} // End of namespace Drascula diff --git a/engines/drascula/module.mk b/engines/drascula/module.mk index 042b227ca3..dfe53ca824 100644 --- a/engines/drascula/module.mk +++ b/engines/drascula/module.mk @@ -1,12 +1,19 @@ MODULE := engines/drascula MODULE_OBJS = \ + actors.o \ animation.o \ + converse.o \ detection.o \ drascula.o \ + graphics.o \ + interface.o \ + objects.o \ + palette.o \ rooms.o \ - talk.o \ - texts.o + saveload.o \ + sound.o \ + talk.o # This module can be built as a plugin diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp new file mode 100644 index 0000000000..01967d975d --- /dev/null +++ b/engines/drascula/objects.cpp @@ -0,0 +1,300 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::pickObject(int object) { + if (currentChapter == 6) + loadPic("iconsp.alg", backSurface); + else if (currentChapter == 4) + loadPic("icons2.alg", backSurface); + else if (currentChapter == 5) + loadPic("icons3.alg", backSurface); + else + loadPic("icons.alg", backSurface); + chooseObject(object); + if (currentChapter == 2) + loadPic(menuBackground, backSurface); + else + loadPic(99, backSurface); +} + +void DrasculaEngine::chooseObject(int object) { + if (currentChapter == 5) { + if (takeObject == 1 && menuScreen == 0 && pickedObject != 16) + addObject(pickedObject); + } else { + if (takeObject == 1 && menuScreen == 0) + addObject(pickedObject); + } + copyBackground(_x1d_menu[object], _y1d_menu[object], 0, 0, OBJWIDTH,OBJHEIGHT, backSurface, drawSurface3); + takeObject = 1; + pickedObject = object; +} + +int DrasculaEngine::removeObject(int obj) { + int result = 1; + + for (int h = 1; h < 43; h++) { + if (inventoryObjects[h] == obj) { + inventoryObjects[h] = 0; + result = 0; + break; + } + } + + return result; +} + +void DrasculaEngine::withoutVerb() { + int c = (menuScreen == 1) ? 0 : 171; + + if (currentChapter == 5) { + if (takeObject == 1 && pickedObject != 16) + addObject(pickedObject); + } else { + if (takeObject == 1) + addObject(pickedObject); + } + copyBackground(0, c, 0, 0, OBJWIDTH,OBJHEIGHT, backSurface, drawSurface3); + + takeObject = 0; + hasName = 0; +} + +void DrasculaEngine::gotoObject(int pointX, int pointY) { + if (currentChapter == 5 || currentChapter == 6) { + if (hare_se_ve == 0) { + curX = roomX; + curY = roomY; + updateRoom(); + updateScreen(); + return; + } + } + roomX = pointX; + roomY = pointY; + startWalking(); + + for (;;) { + updateRoom(); + updateScreen(); + if (characterMoved == 0) + break; + } + + if (walkToObject == 1) { + walkToObject = 0; + trackProtagonist = trackFinal; + } + updateRoom(); + updateScreen(); +} + +void DrasculaEngine::checkObjects() { + int l, veo = 0; + + for (l = 0; l < numRoomObjs; l++) { + if (mouseX > x1[l] && mouseY > y1[l] + && mouseX < x2[l] && mouseY < y2[l] + && visible[l] == 1 && isDoor[l] == 0) { + strcpy(textName, objName[l]); + hasName = 1; + veo = 1; + } + } + + if (mouseX > curX + 2 && mouseY > curY + 2 + && mouseX < curX + curWidth - 2 && mouseY < curY + curHeight - 2) { + if (currentChapter == 2 || veo == 0) { + strcpy(textName, "hacker"); + hasName = 1; + veo = 1; + } + } + + if (veo == 0) + hasName = 0; +} + +void DrasculaEngine::removeObject() { + int h = 0, n; + + updateRoom(); + + for (n = 1; n < 43; n++){ + if (whichObject() == n) { + h = inventoryObjects[n]; + inventoryObjects[n] = 0; + if (h != 0) + takeObject = 1; + } + } + + updateEvents(); + + if (takeObject == 1) + chooseObject(h); +} + +bool DrasculaEngine::pickupObject() { + int h = pickedObject; + checkFlags = 1; + + updateRoom(); + showMenu(); + updateScreen(); + + // Objects with an ID smaller than 7 are the inventory verbs + if (pickedObject >= 7) { + for (int n = 1; n < 43; n++) { + if (whichObject() == n && inventoryObjects[n] == 0) { + inventoryObjects[n] = h; + takeObject = 0; + checkFlags = 0; + } + } + } + + if (checkFlags == 1) { + if (checkMenuFlags()) + return true; + } + updateEvents(); + if (takeObject == 0) + withoutVerb(); + + return false; +} + +void DrasculaEngine::addObject(int obj) { + int h, position = 0; + + for (h = 1; h < 43; h++) { + if (inventoryObjects[h] == obj) + position = 1; + } + + if (position == 0) { + for (h = 1; h < 43; h++) { + if (inventoryObjects[h] == 0) { + inventoryObjects[h] = obj; + position = 1; + break; + } + } + } +} + +int DrasculaEngine::whichObject() { + int n = 0; + + for (n = 1; n < 43; n++) { + if (mouseX > _itemLocations[n].x && mouseY > _itemLocations[n].y && + mouseX < _itemLocations[n].x + OBJWIDTH && + mouseY < _itemLocations[n].y + OBJHEIGHT) + break; + } + + return n; +} + +void DrasculaEngine::updateVisible() { + if (currentChapter == 1) { + // nothing + } else if (currentChapter == 2) { + if (roomNumber == 2 && flags[40] == 0) + visible[3] = 0; + else if (roomNumber == 3 && flags[3] == 1) + visible[8] = 0; + else if (roomNumber == 6 && flags[1] == 1 && flags[10] == 0) { + visible[2] = 0; + visible[4] = 1; + } else if (roomNumber == 7 && flags[35] == 1) + visible[3] = 0; + else if (roomNumber == 14 && flags[5] == 1) + visible[4] = 0; + else if (roomNumber == 18 && flags[28] == 1) + visible[2] = 0; + } else if (currentChapter == 3) { + // nothing + } else if (currentChapter == 4) { + if (roomNumber == 23 && flags[0] == 0 && flags[11] == 0) + visible[2] = 1; + if (roomNumber == 23 && flags[0] == 1 && flags[11] == 0) + visible[2] = 0; + if (roomNumber == 21 && flags[10] == 1) + visible[2] = 0; + if (roomNumber == 22 && flags[26] == 1) { + visible[2] = 0; + visible[1] = 1; + } + if (roomNumber == 22 && flags[27] == 1) + visible[3] = 0; + if (roomNumber == 26 && flags[21] == 0) + strcpy(objName[2], _textmisc[_lang][0]); + if (roomNumber == 26 && flags[18] == 1) + visible[2] = 0; + if (roomNumber == 26 && flags[12] == 1) + visible[1] = 0; + if (roomNumber == 35 && flags[14] == 1) + visible[2] = 0; + if (roomNumber == 35 && flags[17] == 1) + visible[3] = 1; + if (roomNumber == 35 && flags[15] == 1) + visible[1] = 0; + } else if (currentChapter == 5) { + if (roomNumber == 49 && flags[6] == 1) + visible[2] = 0; + if (roomNumber == 49 && flags[6] == 0) + visible[1] = 0; + if (roomNumber == 49 && flags[6] == 1) + visible[1] = 1; + if (roomNumber == 45 && flags[6] == 1) + visible[3] = 1; + if (roomNumber == 53 && flags[2] == 1) + visible[3] = 0; + if (roomNumber == 54 && flags[13] == 1) + visible[3] = 0; + if (roomNumber == 55 && flags[8] == 1) + visible[1] = 0; + } else if (currentChapter == 6) { + if (roomNumber == 58 && flags[8] == 0) + isDoor[1] = 0; + if (roomNumber == 58 && flags[8] == 1) + isDoor[1] = 1; + if (roomNumber == 59) + isDoor[1] = 0; + if (roomNumber == 60) { + trackDrascula = 0; + drasculaX = 155; + drasculaY = 69; + } + } +} + +} // End of namespace Drascula diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp new file mode 100644 index 0000000000..ad57bce618 --- /dev/null +++ b/engines/drascula/palette.cpp @@ -0,0 +1,202 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::setRGB(byte *pal, int colorCount) { + int x, cnt = 0; + + for (x = 0; x < colorCount; x++) { + gamePalette[x][0] = pal[cnt++] / 4; + gamePalette[x][1] = pal[cnt++] / 4; + gamePalette[x][2] = pal[cnt++] / 4; + } + setPalette((byte *)&gamePalette); +} + +void DrasculaEngine::black() { + int color, component; + DacPalette256 blackPalette; + + for (color = 0; color < 256; color++) + for (component = 0; component < 3; component++) + blackPalette[color][component] = 0; + + blackPalette[254][0] = 0x3F; + blackPalette[254][1] = 0x3F; + blackPalette[254][2] = 0x15; + + setPalette((byte *)&blackPalette); +} + +void DrasculaEngine::setPalette(byte *PalBuf) { + byte pal[256 * 4]; + int i; + + for (i = 0; i < 256; i++) { + pal[i * 4 + 0] = PalBuf[i * 3 + 0] * 4; + pal[i * 4 + 1] = PalBuf[i * 3 + 1] * 4; + pal[i * 4 + 2] = PalBuf[i * 3 + 2] * 4; + pal[i * 4 + 3] = 0; + } + _system->setPalette(pal, 0, 256); + _system->updateScreen(); +} + +void DrasculaEngine::color_abc(int cl) { + _color = cl; + + char colorTable[][3] = { + { 0, 0, 0 }, { 0x10, 0x3E, 0x28 }, + { 0, 0, 0 }, // unused + { 0x16, 0x3F, 0x16 }, { 0x09, 0x3F, 0x12 }, + { 0x3F, 0x3F, 0x15 }, + { 0, 0, 0 }, // unused + { 0x38, 0, 0 }, { 0x3F, 0x27, 0x0B }, + { 0x2A, 0, 0x2A }, { 0x30, 0x30, 0x30 }, + { 98, 91, 100 } + }; + + for (int i = 0; i <= 2; i++) + gamePalette[254][i] = colorTable[cl][i]; + + setPalette((byte *)&gamePalette); +} + +char DrasculaEngine::adjustToVGA(char value) { + return (value & 0x3F) * (value > 0); +} + +void DrasculaEngine::fadeToBlack(int fadeSpeed) { + char fade; + unsigned int color, component; + + DacPalette256 palFade; + + for (fade = 63; fade >= 0; fade--) { + for (color = 0; color < 256; color++) { + for (component = 0; component < 3; component++) { + palFade[color][component] = adjustToVGA(gamePalette[color][component] - 63 + fade); + } + } + pause(fadeSpeed); + + setPalette((byte *)&palFade); + } +} + +void DrasculaEngine::fadeFromBlack(int fadeSpeed) { + char fade; + unsigned int color, component; + + DacPalette256 palFade; + + for (fade = 0; fade < 64; fade++) { + for (color = 0; color < 256; color++) { + for (component = 0; component < 3; component++) { + palFade[color][component] = adjustToVGA(gamePalette[color][component] - 63 + fade); + } + } + pause(fadeSpeed); + + setPalette((byte *)&palFade); + } +} + +void DrasculaEngine::assignDefaultPalette() { + int color, component; + + for (color = 235; color < 253; color++) + for (component = 0; component < 3; component++) + defaultPalette[color][component] = gamePalette[color][component]; +} + +void DrasculaEngine::assignBrightPalette() { + int color, component; + + for (color = 235; color < 253; color++) { + for (component = 0; component < 3; component++) + brightPalette[color][component] = gamePalette[color][component]; + } +} + +void DrasculaEngine::assignDarkPalette() { + int color, component; + + for (color = 235; color < 253; color++) { + for (component = 0; component < 3; component++) + darkPalette[color][component] = gamePalette[color][component]; + } +} + +void DrasculaEngine::setDefaultPalette() { + int color, component; + + for (color = 235; color < 253; color++) { + for (component = 0; component < 3; component++) { + gamePalette[color][component] = defaultPalette[color][component]; + } + } + setPalette((byte *)&gamePalette); +} + +void DrasculaEngine::setBrightPalette() { + int color, component; + + for (color = 235; color < 253; color++) { + for (component = 0; component < 3; component++) + gamePalette[color][component] = brightPalette[color][component]; + } + + setPalette((byte *)&gamePalette); +} + +void DrasculaEngine::setDarkPalette() { + int color, component; + + for (color = 235; color < 253; color++ ) + for (component = 0; component < 3; component++) + gamePalette[color][component] = darkPalette[color][component]; + + setPalette((byte *)&gamePalette); +} + +void DrasculaEngine::setPaletteBase(int darkness) { + char fade; + unsigned int color, component; + + for (fade = darkness; fade >= 0; fade--) { + for (color = 235; color < 253; color++) { + for (component = 0; component < 3; component++) + gamePalette[color][component] = adjustToVGA(gamePalette[color][component] - 8 + fade); + } + } + + setPalette((byte *)&gamePalette); +} + +} // End of namespace Drascula diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index ba2f0d56b8..6fe28bdbdc 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -23,761 +23,584 @@ * */ +#include "common/array.h" + #include "drascula/drascula.h" namespace Drascula { -static const int mirar_t[3] = {100, 101, 54}; -static const char mirar_v[3][14] = {"100.als", "101.als", "54.als"}; -static const int poder_t[6] = {11, 109, 111, 110, 115, 116}; -static const char poder_v[6][14] = {"11.als", "109.als", "111.als", "110.als", "115.als", "116.als"}; - -void DrasculaEngine::room_0() { - if (num_ejec == 1) { - if (objeto_que_lleva == LOOK) - talk(_text[_lang][54], "54.als"); - else if (objeto_que_lleva == MOVE) - talk(_text[_lang][19], "19.als"); - else if (objeto_que_lleva == PICK) - talk(_text[_lang][11], "11.als"); - else if (objeto_que_lleva == OPEN) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == CLOSE) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == TALK) - talk(_text[_lang][16], "16.als"); - else - talk(_text[_lang][11],"11.als"); - } else if (num_ejec == 2) { - if (objeto_que_lleva == LOOK) { - talk(_text[_lang][mirar_t[c_mirar]], mirar_v[c_mirar]); - c_mirar++; - if (c_mirar == 3) - c_mirar = 0; - } else if (objeto_que_lleva == MOVE) { - talk(_text[_lang][19], "19.als"); - } else if (objeto_que_lleva == PICK) { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } else if (objeto_que_lleva == OPEN) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == CLOSE) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == TALK) - talk(_text[_lang][16], "16.als"); - else { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } - } else if (num_ejec == 3) { - if (objeto_que_lleva == LOOK) - talk(_text[_lang][316], "316.als"); - else if (objeto_que_lleva == MOVE) - talk(_text[_lang][317], "317.als"); - else if (objeto_que_lleva == PICK) - talk(_text[_lang][318], "318.als"); - else if (objeto_que_lleva == OPEN) - talk(_text[_lang][319], "319.als"); - else if (objeto_que_lleva == CLOSE) - talk(_text[_lang][319], "319.als"); - else if (objeto_que_lleva == TALK) - talk(_text[_lang][320], "320.als"); - else - talk(_text[_lang][318], "318.als"); - } else if (num_ejec == 4) { - if (objeto_que_lleva == LOOK) { - talk(_text[_lang][mirar_t[c_mirar]], mirar_v[c_mirar]); - c_mirar++; - if (c_mirar == 3) - c_mirar = 0; - } else if (objeto_que_lleva == MOVE) - talk(_text[_lang][19], "19.als"); - else if (objeto_que_lleva == PICK) { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } else if (objeto_que_lleva == OPEN) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == CLOSE) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == TALK) - talk(_text[_lang][16], "16.als"); - else { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } - } else if (num_ejec == 5) { - if (objeto_que_lleva == LOOK) { - talk(_text[_lang][mirar_t[c_mirar]], mirar_v[c_mirar]); - c_mirar++; - if (c_mirar == 3) - c_mirar = 0; - } else if (objeto_que_lleva == MOVE) - talk(_text[_lang][19], "19.als"); - else if (objeto_que_lleva == PICK) { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } else if (objeto_que_lleva == OPEN) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == CLOSE) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == TALK) - talk(_text[_lang][16], "16.als"); - else { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } - } else if (num_ejec == 6) { - if (objeto_que_lleva == LOOK) { - talk(_text[_lang][mirar_t[c_mirar]], mirar_v[c_mirar]); - c_mirar++; - if (c_mirar == 3) - c_mirar = 0; - } else if (objeto_que_lleva == MOVE) - talk(_text[_lang][19], "19.als"); - else if (objeto_que_lleva == PICK) { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; - } else if (objeto_que_lleva == OPEN) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == CLOSE) - talk(_text[_lang][9], "9.als"); - else if (objeto_que_lleva == TALK) - talk(_text[_lang][16], "16.als"); - else { - talk(_text[_lang][poder_t[c_poder]], poder_v[c_poder]); - c_poder++; - if (c_poder == 6) - c_poder = 0; +typedef bool (DrasculaEngine::*RoomParser)(int args); + +struct DrasculaRoomParser { + DrasculaRoomParser(const char* d, RoomParser p) : desc(d), proc(p) {} + const char* desc; + RoomParser proc; +}; + +typedef void (DrasculaEngine::*Updater)(); + +struct DrasculaUpdater { + DrasculaUpdater(const char* d, Updater p) : desc(d), proc(p) {} + const char* desc; + Updater proc; +}; + +Common::Array<DrasculaRoomParser*> _roomParsers; +Common::Array<DrasculaUpdater*> _roomPreupdaters; +Common::Array<DrasculaUpdater*> _roomUpdaters; + +#define ROOM(x) _roomParsers.push_back(new DrasculaRoomParser(#x, &DrasculaEngine::x)) +#define PREUPDATEROOM(x) _roomPreupdaters.push_back(new DrasculaUpdater(#x, &DrasculaEngine::x)) +#define UPDATEROOM(x) _roomUpdaters.push_back(new DrasculaUpdater(#x, &DrasculaEngine::x)) + +void DrasculaEngine::setupRoomsTable() { + ROOM(room_0); // default + ROOM(room_1); + ROOM(room_3); + ROOM(room_4); + ROOM(room_5); + ROOM(room_6); + ROOM(room_7); + ROOM(room_8); + ROOM(room_9); + ROOM(room_12); + ROOM(room_13); // returns bool + ROOM(room_14); + ROOM(room_15); + ROOM(room_16); + ROOM(room_17); + ROOM(room_18); + ROOM(room_21); // returns bool + ROOM(room_22); + ROOM(room_23); + ROOM(room_24); + ROOM(room_26); + ROOM(room_27); + ROOM(room_29); + ROOM(room_30); + ROOM(room_31); + ROOM(room_34); + ROOM(room_35); + ROOM(room_49); + ROOM(room_53); + ROOM(room_54); + ROOM(room_55); + ROOM(room_56); // returns bool + ROOM(room_58); + ROOM(room_59); + ROOM(room_60); // returns bool + ROOM(room_62); + ROOM(room_102); + + PREUPDATEROOM(update_1_pre); + PREUPDATEROOM(update_6_pre); + PREUPDATEROOM(update_9_pre); + PREUPDATEROOM(update_14_pre); + PREUPDATEROOM(update_16_pre); + PREUPDATEROOM(update_18_pre); + PREUPDATEROOM(update_23_pre); + PREUPDATEROOM(update_26_pre); + PREUPDATEROOM(update_35_pre); + PREUPDATEROOM(update_58_pre); + PREUPDATEROOM(update_59_pre); + PREUPDATEROOM(update_60_pre); + PREUPDATEROOM(update_62_pre); + + UPDATEROOM(update_2); + UPDATEROOM(update_3); + UPDATEROOM(update_4); + UPDATEROOM(update_13); + UPDATEROOM(update_26); + UPDATEROOM(update_58); + UPDATEROOM(update_60); + UPDATEROOM(update_62); + UPDATEROOM(update_102); +} + +bool DrasculaEngine::roomParse(int rN, int fl) { + bool seen = false; + + for (int i = 0; i < _roomActionsSize; i++) { + if (_roomActions[i].room == rN) { + seen = true; + if (_roomActions[i].chapter == currentChapter || + _roomActions[i].chapter == -1) { + if (_roomActions[i].action == pickedObject || + _roomActions[i].action == kVerbDefault) { + if (_roomActions[i].objectID == fl || + _roomActions[i].objectID == -1) { + talk(_roomActions[i].speechID); + hasAnswer = 1; + return true; + } + } + } + } else if (seen) // Stop searching down the list + break; + } + + return false; +} + +bool DrasculaEngine::room_0(int fl) { + static const int lookExcuses[3] = {100, 101, 54}; + static const int actionExcuses[6] = {11, 109, 111, 110, 115, 116}; + + fl = -1; // avoid warning + + // non-default actions + if (currentChapter == 2 || currentChapter == 4 || + currentChapter == 5 || currentChapter == 6) { + if (pickedObject == kVerbLook) { + talk(lookExcuses[curExcuseLook]); + curExcuseLook++; + if (curExcuseLook == 3) + curExcuseLook = 0; + } else { + talk(actionExcuses[curExcuseAction]); + curExcuseAction++; + if (curExcuseAction == 6) + curExcuseAction = 0; } } + + return true; } -void DrasculaEngine::room_1(int fl) { - if (objeto_que_lleva == LOOK && fl == 118) { - talk(_text[_lang][1], "1.als"); +bool DrasculaEngine::room_1(int fl) { + if (pickedObject == kVerbLook && fl == 118) { + talk(1); pause(10); - talk(_text[_lang][2], "2.als"); - } else if (objeto_que_lleva == PICK && fl == 118) - talk(_text[_lang][5], "5.als"); - else if (objeto_que_lleva == OPEN && fl == 118) - talk(_text[_lang][3], "3.als"); - else if (objeto_que_lleva == CLOSE && fl == 118) - talk(_text[_lang][4], "4.als"); - else if (objeto_que_lleva == TALK && fl == 118) - talk(_text[_lang][6], "6.als"); - else if (objeto_que_lleva == LOOK && fl == 119) - talk(_text[_lang][8], "8.als"); - else if (objeto_que_lleva == MOVE && fl == 119) - talk(_text[_lang][13], "13.als"); - else if (objeto_que_lleva == CLOSE && fl == 119) - talk(_text[_lang][10], "10.als"); - else if (objeto_que_lleva == TALK && fl == 119) - talk(_text[_lang][12], "12.als"); - else if (objeto_que_lleva == LOOK && fl == 120 && flags[8] == 0) - talk(_text[_lang][14], "14.als"); - else if (objeto_que_lleva == MOVE && fl == 120) - talk(_text[_lang][13], "13.als"); - else if (objeto_que_lleva == OPEN && fl == 120) - talk(_text[_lang][18], "18.als"); - else if (objeto_que_lleva == TALK && fl == 120) - talk(_text[_lang][15], "15.als"); + talk(2); + } else if (pickedObject == kVerbLook && fl == 120 && flags[8] == 0) + talk(14); else - hay_respuesta = 0; -} - -void DrasculaEngine::room_3(int fl) { - if (objeto_que_lleva == LOOK && fl == 129) - talk(_text[_lang][21], "21.als"); - else if (objeto_que_lleva == PICK && fl == 129) - talk(_text[_lang][5], "5.als"); - else if (objeto_que_lleva == MOVE && fl == 129) - talk(_text[_lang][24], "24.als"); - else if (objeto_que_lleva == OPEN && fl == 129) - talk(_text[_lang][22], "22.als"); - else if (objeto_que_lleva == CLOSE && fl == 129) - talk(_text[_lang][10], "10.als"); - else if (objeto_que_lleva == TALK && fl == 129) { - talk(_text[_lang][23], "23.als"); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_3(int fl) { + if (pickedObject == kVerbTalk && fl == 129) { + talk(23); pause(6); - talk_sinc(_text[_lang][50], "50.als", "11111111111144432554433"); - } else if (objeto_que_lleva == LOOK && fl == 131) - talk(_text[_lang][27], "27.als"); - else if (objeto_que_lleva == PICK && fl == 131) - talk(_text[_lang][5], "5.als"); - else if (objeto_que_lleva == MOVE && fl == 131) - talk(_text[_lang][24], "24.als"); - else if (objeto_que_lleva == OPEN && fl == 131) - talk(_text[_lang][22], "22.als"); - else if (objeto_que_lleva == CLOSE && fl == 131) - talk(_text[_lang][10], "10.als"); - else if (objeto_que_lleva == TALK && fl == 131) - talk(_text[_lang][23], "23.als"); - else if (objeto_que_lleva == LOOK && fl == 132) - talk(_text[_lang][28], "28.als"); - else if (objeto_que_lleva == PICK && fl == 132) - talk(_text[_lang][5], "5.als"); - else if (objeto_que_lleva == MOVE && fl == 132) - talk(_text[_lang][24], "24.als"); - else if (objeto_que_lleva == OPEN && fl == 132) - talk(_text[_lang][22], "22.als"); - else if (objeto_que_lleva == CLOSE && fl == 132) - talk(_text[_lang][10], "10.als"); - else if (objeto_que_lleva == TALK && fl == 132) - talk(_text[_lang][23], "23.als"); - else if (objeto_que_lleva == LOOK && fl == 133) - talk(_text[_lang][321], "321.als"); - else if (objeto_que_lleva == PICK && fl == 133) - talk(_text[_lang][31], "31.als"); - else if (objeto_que_lleva == MOVE && fl == 133) - talk(_text[_lang][34], "34.als"); - else if (objeto_que_lleva == OPEN && fl == 133) - talk(_text[_lang][30], "30.als"); - else if (objeto_que_lleva == CLOSE && fl == 133) - talk(_text[_lang][10], "10.als"); - else if (objeto_que_lleva == TALK && fl == 133) { - talk_sinc(_text[_lang][322], "322.als", "13333334125433333333"); + talk_sync(_text[_lang][50], "50.als", "11111111111144432554433"); + } else if (pickedObject == kVerbTalk && fl == 133) { + talk_sync(_text[_lang][322], "322.als", "13333334125433333333"); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(25); - talk(_text[_lang][33], "33.als"); - } else if (objeto_que_lleva == LOOK && fl == 165) { - talk(_text[_lang][149], "149.als"); - talk(_text[_lang][150], "150.als"); - } else if (objeto_que_lleva == PICK && fl == 165) { - copyBackground(0, 0, 0,0, 320, 200, dir_dibujo1, dir_zona_pantalla); + talk(33); + } else if (pickedObject == kVerbLook && fl == 165) { + talk(149); + talk(150); + } else if (pickedObject == kVerbPick && fl == 165) { + copyBackground(0, 0, 0,0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - copyRect(44, 1, hare_x, hare_y, 41, 70, dir_dibujo2, dir_zona_pantalla); + copyRect(44, 1, curX, curY, 41, 70, drawSurface2, screenSurface); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(4); - agarra_objeto(10); + pickObject(10); flags[3] = 1; visible[8] = 0; - } else if (objeto_que_lleva == LOOK && fl == 166) - talk(_text[_lang][55], "55.als"); - else if (objeto_que_lleva == PICK && fl == 166) - talk(_text[_lang][7], "7.als"); - else if (objeto_que_lleva == 14 && fl == 166 && flags[37] == 0) { + } else if (pickedObject == 14 && fl == 166 && flags[37] == 0) { animation_7_2(); - agarra_objeto(8); - } else if (objeto_que_lleva == 14 && fl == 166 && flags[37] == 1) - talk(_text[_lang][323], "323.als"); - else if (objeto_que_lleva == LOOK && fl == 211) - talk(_text[_lang][184], "184.als"); - else if (objeto_que_lleva == TALK && fl == 211) { - talk(_text[_lang][185], "185.als"); - talk(_text[_lang][186], "186.als"); + pickObject(8); + } else if (pickedObject == 14 && fl == 166 && flags[37] == 1) + talk(323); + else if (pickedObject == kVerbTalk && fl == 211) { + talk(185); + talk(186); } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_4(int fl) { - if (objeto_que_lleva == MOVE && fl == 189 && flags[34] == 0) { - talk(_text[_lang][327], "327.als"); - agarra_objeto(13); +bool DrasculaEngine::room_4(int fl) { + if (pickedObject == kVerbMove && fl == 189 && flags[34] == 0) { + talk(327); + pickObject(13); flags[34] = 1; if (flags[7] == 1 && flags[26] == 1 && flags[34] == 1 && flags[35] == 1 && flags[37] == 1) flags[38] = 1; - } else if (objeto_que_lleva == LOOK && fl == 189) - talk(_text[_lang][182], "182.als"); - else if (objeto_que_lleva == LOOK && fl == 207) - talk(_text[_lang][175], "175.als"); - else if (objeto_que_lleva == TALK && fl == 207) - talk(_text[_lang][176], "176.als"); - else if (objeto_que_lleva == LOOK && fl == 208) - talk(_text[_lang][177], "177.als"); - else if (objeto_que_lleva == LOOK && fl == 209) - talk(_text[_lang][179], "179.als"); - else if (objeto_que_lleva == LOOK && fl == 210) - talk(_text[_lang][180], "180.als"); - else if (objeto_que_lleva == OPEN && fl == 210) - talk(_text[_lang][181], "181.als"); - else - hay_respuesta = 0; -} - -void DrasculaEngine::room_5(int fl) { - if (objeto_que_lleva == LOOK && fl == 136 && flags[8]==0) talk(_text[_lang][14], "14.als"); - else if (objeto_que_lleva == MOVE && fl == 136) - talk(_text[_lang][13], "13.als"); - else if (objeto_que_lleva == OPEN && fl == 136) - talk(_text[_lang][18], "18.als"); - else if (objeto_que_lleva == TALK && fl == 136) - talk(_text[_lang][15], "15.als"); - else if (objeto_que_lleva == 10 && fl == 136) { + } else + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_5(int fl) { + if (pickedObject == kVerbLook && fl == 136 && flags[8] == 0) + talk(14); + else if (pickedObject == 10 && fl == 136) { animation_5_2(); - resta_objeto(10); - } else if (objeto_que_lleva == LOOK && fl == 212) - talk(_text[_lang][187], "187.als"); - else if (objeto_que_lleva == TALK && fl == 212) - talk(_text[_lang][188], "188.als"); - else if (objeto_que_lleva == LOOK && fl == 213) - talk(_text[_lang][189], "189.als"); - else if (objeto_que_lleva == OPEN && fl == 213) - talk(_text[_lang][190], "190.als"); - else - hay_respuesta = 0; -} - -void DrasculaEngine::room_6(int fl){ - if (objeto_que_lleva == LOOK && fl==144) { - talk(_text[_lang][41], "41.als"); - talk(_text[_lang][42], "42.als"); - } else if (objeto_que_lleva == PICK && fl == 144) - talk(_text[_lang][43], "43.als"); - else if (objeto_que_lleva == LOOK && fl == 138) - talk(_text[_lang][35], "35.als"); - else if (objeto_que_lleva == OPEN && fl == 138) - abre_puerta(0, 1); - else if (objeto_que_lleva == CLOSE && fl == 138) - cierra_puerta(0, 1); - else if (objeto_que_lleva == TALK && fl == 138) - talk(_text[_lang][6], "6.als"); - else if (objeto_que_lleva == LOOK && fl == 143) - talk(_text[_lang][37], "37.als"); - else if (objeto_que_lleva == PICK && fl == 143) - talk(_text[_lang][7], "7.als"); - else if (objeto_que_lleva == MOVE && fl == 143) - talk(_text[_lang][7], "7.als"); - else if (objeto_que_lleva == OPEN && fl == 143 && flags[2] == 0) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateRefresh_pre(); - copyRect(228, 102, hare_x + 5, hare_y - 1, 47, 73, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - pause(10); - comienza_sound("s3.als"); - flags[2] = 1; - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); - } else if (objeto_que_lleva == CLOSE && fl == 143 && flags[2] == 1) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + removeObject(kItemSpike); + } else + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_6(int fl) { + if (pickedObject == kVerbLook && fl==144) { + talk(41); + talk(42); + } else if (pickedObject == kVerbOpen && fl == 138) + openDoor(0, 1); + else if (pickedObject == kVerbClose && fl == 138) + closeDoor(0, 1); + else if (pickedObject == kVerbOpen && fl == 143 && flags[2] == 0) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateRefresh_pre(); + copyRect(228, 102, curX + 5, curY - 1, 47, 73, drawSurface3, screenSurface); + updateScreen(); + pause(10); + playSound(3); + flags[2] = 1; + updateRoom(); + updateScreen(); + finishSound(); + } else if (pickedObject == kVerbClose && fl == 143 && flags[2] == 1) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); flags[2] = 0; updateRefresh_pre(); - copyRect(228, 102, hare_x + 5, hare_y - 1, 47, 73, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRect(228, 102, curX + 5, curY - 1, 47, 73, drawSurface3, screenSurface); + updateScreen(); pause(5); - comienza_sound("s4.als"); + playSound(4); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); - } else if (objeto_que_lleva == TALK && fl == 143) - talk(_text[_lang][38], "38.als"); - else if (objeto_que_lleva == LOOK && fl == 139) - talk(_text[_lang][36], "36.als"); - else if (objeto_que_lleva == OPEN && fl == 139 && flags[1] == 0) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + updateScreen(); + finishSound(); + } else if (pickedObject == kVerbOpen && fl == 139 && flags[1] == 0) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - copyRect(267, 1, hare_x - 14, hare_y - 2, 52, 73, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRect(267, 1, curX - 14, curY - 2, 52, 73, drawSurface3, screenSurface); + updateScreen(); pause(19); - comienza_sound("s3.als"); + playSound(3); flags[1] = 1; visible[4] = 1; visible[2] = 0; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - fin_sound(); - } else if (objeto_que_lleva == LOOK && fl == 140) - talk(_text[_lang][147], "147.als"); - else if (objeto_que_lleva == PICK && fl == 140) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + updateScreen(); + finishSound(); + } else if (pickedObject == kVerbPick && fl == 140) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - copyRect(267, 1, hare_x - 14, hare_y - 2, 52, 73, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRect(267, 1, curX - 14, curY - 2, 52, 73, drawSurface3, screenSurface); + updateScreen(); pause(19); - agarra_objeto(9); + pickObject(9); visible[4] = 0; flags[10] = 1; - } else if (objeto_que_lleva == OPEN && fl == 140) - hay_respuesta = 1; + } else if (pickedObject == kVerbOpen && fl == 140) + hasAnswer = 1; else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_7(int fl){ - if (objeto_que_lleva == LOOK && fl == 169) - talk(_text[_lang][44], "44.als"); - else if (objeto_que_lleva == LOOK && fl == 164) - talk(_text[_lang][35], "35.als" ); - else if (objeto_que_lleva == PICK && fl == 190) { - agarra_objeto(17); +bool DrasculaEngine::room_7(int fl) { + if (pickedObject == kVerbPick && fl == 190) { + pickObject(17); flags[35] = 1; visible[3] = 0; if (flags[7] == 1 && flags[26] == 1 && flags[34] == 1 && flags[35] == 1 && flags[37] == 1) flags[38] = 1; } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_8(int fl) { - if (objeto_que_lleva == LOOK && fl == 147 && flags[7] == 0) { - talk(_text[_lang][58], "58.als"); - agarra_objeto(15); - flags[7] = 1; - if (flags[7] == 1 && flags[26] == 1 && flags[34] == 1 && flags[35] == 1 && flags[37] == 1) - flags[38] = 1; - } else if (objeto_que_lleva == LOOK && fl == 147) - talk(_text[_lang][59], "59.als"); - else - hay_respuesta = 0; +bool DrasculaEngine::room_8(int fl) { + if (pickedObject == kVerbLook && fl == 147) { + if (flags[7] == 0) { + talk(58); + pickObject(15); + flags[7] = 1; + if (flags[7] == 1 && flags[26] == 1 && flags[34] == 1 && flags[35] == 1 && flags[37] == 1) + flags[38] = 1; + } else { + talk(59); + } + } else + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_9(int fl){ - if (objeto_que_lleva == LOOK && fl == 150) - talk(_text[_lang][35], "35.als"); - else if (objeto_que_lleva == TALK && fl == 150) - talk(_text[_lang][6], "6.als"); - else if (objeto_que_lleva == LOOK && fl == 51) - talk(_text[_lang][60], "60.als"); - else if (objeto_que_lleva == TALK && fl == 51 && flags[4] == 0) +bool DrasculaEngine::room_9(int fl) { + if (pickedObject == kVerbTalk && fl == 51 && flags[4] == 0) animation_4_2(); - else if (objeto_que_lleva == TALK && fl == 51 && flags[4] == 1) + else if (pickedObject == kVerbTalk && fl == 51 && flags[4] == 1) animation_33_2(); - else if (objeto_que_lleva == 7 && fl == 51) { + else if (pickedObject == 7 && fl == 51) { animation_6_2(); - resta_objeto(7); - agarra_objeto(14);} + removeObject(kItemMoney); + pickObject(14);} else - hay_respuesta = 0; -} - -void DrasculaEngine::room_12(int fl){ - if (objeto_que_lleva == LOOK && fl == 154) - talk(_text[_lang][329], "329.als"); - else if (objeto_que_lleva == TALK && fl == 154) - talk(_text[_lang][330], "330.als"); - else if (objeto_que_lleva == MOVE && fl == 155) - talk(_text[_lang][48], "48.als"); - else if (objeto_que_lleva == TALK && fl == 155) - talk(_text[_lang][331], "331.als"); - else if (objeto_que_lleva == LOOK && fl == 156) - talk(_text[_lang][35], "35.als"); - else if (objeto_que_lleva == MOVE && fl == 156) - talk(_text[_lang][48], "48.als"); - else if (objeto_que_lleva == TALK && fl == 156) - talk(_text[_lang][50], "50.als"); - else if (objeto_que_lleva == OPEN && fl == 156) - abre_puerta(16, 4); - else if (objeto_que_lleva == CLOSE && fl == 156) - cierra_puerta(16, 4); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_12(int fl) { + if (pickedObject == kVerbOpen && fl == 156) + openDoor(16, 4); + else if (pickedObject == kVerbClose && fl == 156) + closeDoor(16, 4); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } bool DrasculaEngine::room_13(int fl) { - if (objeto_que_lleva == LOOK && fl == 51) { - talk(_text[_lang][411], "411.als"); - sentido_hare = 3; - talk(_text[_lang][412], "412.als"); - strcpy(nombre_obj[1], "yoda"); - } else if (objeto_que_lleva == TALK && fl == 51) - conversa("op_7.cal"); - else if (objeto_que_lleva == 19 && fl == 51) + if (pickedObject == kVerbLook && fl == 51) { + talk(411); + trackProtagonist = 3; + talk(412); + strcpy(objName[1], "yoda"); + } else if (pickedObject == kVerbTalk && fl == 51) + converse(7); + else if (pickedObject == 19 && fl == 51) animation_1_3(); - else if (objeto_que_lleva == 9 && fl == 51) { + else if (pickedObject == 9 && fl == 51) { animation_2_3(); return true; } else - hay_respuesta = 0; + hasAnswer = 0; + return false; } -void DrasculaEngine::room_14(int fl) { - if (objeto_que_lleva == TALK && fl == 54 && flags[39] == 0) +bool DrasculaEngine::room_14(int fl) { + if (pickedObject == kVerbTalk && fl == 54 && flags[39] == 0) animation_12_2(); - else if (objeto_que_lleva == TALK && fl == 54 && flags[39] == 1) - talk(_text[_lang][109], "109.als"); - else if (objeto_que_lleva == 12 && fl == 54) + else if (pickedObject == kVerbTalk && fl == 54 && flags[39] == 1) + talk(109); + else if (pickedObject == 12 && fl == 54) animation_26_2(); - else if (objeto_que_lleva == TALK && fl == 52 && flags[5] == 0) + else if (pickedObject == kVerbTalk && fl == 52 && flags[5] == 0) animation_11_2(); - else if (objeto_que_lleva == TALK && fl == 52 && flags[5] == 1) + else if (pickedObject == kVerbTalk && fl == 52 && flags[5] == 1) animation_36_2(); - else if (objeto_que_lleva == TALK && fl == 53) + else if (pickedObject == kVerbTalk && fl == 53) animation_13_2(); - else if (objeto_que_lleva == LOOK && fl == 200) - talk(_text[_lang][165], "165.als"); - else if (objeto_que_lleva == LOOK && fl == 201) - talk(_text[_lang][166], "166.als"); - else if (objeto_que_lleva == LOOK && fl == 202) - talk(_text[_lang][167], "167.als"); - else if (objeto_que_lleva == LOOK && fl == 203) - talk(_text[_lang][168], "168.als"); - else if (objeto_que_lleva == PICK && fl == 203) - talk(_text[_lang][170], "170.als"); - else if (objeto_que_lleva == MOVE && fl == 203) - talk(_text[_lang][170], "170.als"); - else if (objeto_que_lleva == TALK && fl == 203) - talk(_text[_lang][169], "169.als"); - else if (objeto_que_lleva == LOOK && fl == 204) - talk(_text[_lang][171], "171.als"); else - hay_respuesta = 0; -} - -void DrasculaEngine::room_15(int fl) { - if (objeto_que_lleva == TALK && fl == 188) - talk(_text[_lang][333], "333.als"); - else if (objeto_que_lleva == LOOK && fl == 188) - talk(_text[_lang][334], "334.als"); - else if (objeto_que_lleva == 19 && fl == 188 && flags[27] == 0) - talk(_text[_lang][335], "335.als"); - else if (objeto_que_lleva == 19 && fl == 188 && flags[27] == 1) { - talk(_text[_lang][336], "336.als"); - sentido_hare = 3; - talk(_text[_lang][337], "337.als"); - talk_sinc(_text[_lang][46], "46.als", "4442444244244"); - sentido_hare = 1; - } else if (objeto_que_lleva == 18 && fl == 188 && flags[26] == 0) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - copyRect(133, 135, hare_x + 6, hare_y, 39, 63, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - comienza_sound("s8.als"); - fin_sound(); - talk(_text[_lang][338], "338.als"); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_15(int fl) { + if (pickedObject == 19 && fl == 188 && flags[27] == 0) + talk(335); + else if (pickedObject == 19 && fl == 188 && flags[27] == 1) { + talk(336); + trackProtagonist = 3; + talk(337); + talk_sync(_text[_lang][46], "46.als", "4442444244244"); + trackProtagonist = 1; + } else if (pickedObject == 18 && fl == 188 && flags[26] == 0) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyRect(133, 135, curX + 6, curY, 39, 63, drawSurface3, screenSurface); + updateScreen(); + playSound(8); + finishSound(); + talk(338); flags[27] = 0; - agarra_objeto(19); - resta_objeto(18); - } else if (objeto_que_lleva == MOVE && fl == 188 && flags[27] == 0) { + pickObject(19); + removeObject(kItemTwoCoins); + } else if (pickedObject == kVerbMove && fl == 188 && flags[27] == 0) { animation_34_2(); - talk(_text[_lang][339], "339.als"); - agarra_objeto(16); + talk(339); + pickObject(16); flags[26] = 1; flags[27] = 1; if (flags[7] == 1 && flags[26] == 1 && flags[34] == 1 && flags[35] == 1 && flags[37] == 1) flags[38] = 1; - } else if (objeto_que_lleva == LOOK && fl == 205) - talk(_text[_lang][172], "172.als"); - else if (objeto_que_lleva == LOOK && fl == 206) - talk(_text[_lang][173], "173.als"); - else if (objeto_que_lleva == MOVE && fl == 206) - talk(_text[_lang][174], "174.als"); - else if (objeto_que_lleva == OPEN && fl == 206) - talk(_text[_lang][174], "174.als"); - else - hay_respuesta = 0; -} - -void DrasculaEngine::room_16(int fl) { - if (objeto_que_lleva == TALK && fl == 163) - talk(_text[_lang][6], "6.als"); - else if (objeto_que_lleva == OPEN && fl == 163) - abre_puerta(17, 0); - else if (objeto_que_lleva == CLOSE && fl == 163) - cierra_puerta(17, 0); - else if (objeto_que_lleva == LOOK && fl == 183) - talk(_text[_lang][340], "340.als"); - else if (objeto_que_lleva == TALK && fl == 183) { - talk(_text[_lang][341], "341.als"); + } else + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_16(int fl) { + if (pickedObject == kVerbOpen && fl == 163) + openDoor(17, 0); + else if (pickedObject == kVerbClose && fl == 163) + closeDoor(17, 0); + else if (pickedObject == kVerbTalk && fl == 183) { + talk(341); pause(10); - talk_sinc(_text[_lang][50], "50.als", "11111111111144432554433"); + talk_sync(_text[_lang][50], "50.als", "11111111111144432554433"); pause(3); - talk_baul("bla, bla, bla.", "d83.als"); - } else if (objeto_que_lleva == OPEN && fl == 183) { - abre_puerta(19, NO_PUERTA); + talk_baul(83); + } else if (pickedObject == kVerbOpen && fl == 183) { + openDoor(19, NO_DOOR); if (flags[20] == 0) { flags[20] = 1; - sentido_hare = 3; + trackProtagonist = 3; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk(_text[_lang][342], "342.als"); - agarra_objeto(22); + updateScreen(); + talk(342); + pickObject(22); } - } else if (objeto_que_lleva == CLOSE && fl == 183) - cierra_puerta(19, NO_PUERTA); - else if (objeto_que_lleva == LOOK && fl == 185) - talk(_text[_lang][37], "37.als"); - else if (objeto_que_lleva == PICK && fl == 185) - talk(_text[_lang][7], "7.als"); - else if (objeto_que_lleva == MOVE && fl == 185) - talk(_text[_lang][7], "7.als"); - else if (objeto_que_lleva == TALK && fl == 185) - talk(_text[_lang][38], "38.als"); - else if (objeto_que_lleva == LOOK && fl == 187) { - talk(_text[_lang][343], "343.als"); - sentido_hare = 3; + } else if (pickedObject == kVerbClose && fl == 183) + closeDoor(19, NO_DOOR); + else if (pickedObject == kVerbLook && fl == 187) { + talk(343); + trackProtagonist = 3; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - talk(_text[_lang][344], "344.als"); - } else if (objeto_que_lleva == TALK && fl == 187) - talk(_text[_lang][345], "345.als"); - else - hay_respuesta = 0; + updateScreen(); + talk(344); + } else + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_17(int fl) { - if (objeto_que_lleva == LOOK && fl == 177) - talk(_text[_lang][35], "35.als"); - else if (objeto_que_lleva == TALK && fl == 177 && flags[18] == 0) - talk(_text[_lang][6], "6.als"); - else if (objeto_que_lleva == TALK && fl == 177 && flags[18] == 1) +bool DrasculaEngine::room_17(int fl) { + if (pickedObject == kVerbLook && fl == 177) + talk(35); + else if (pickedObject == kVerbTalk && fl == 177 && flags[18] == 0) + talk(6); + else if (pickedObject == kVerbTalk && fl == 177 && flags[18] == 1) animation_18_2(); - else if (objeto_que_lleva == OPEN && fl == 177 && flags[18] == 1) - talk(_text[_lang][346], "346.als"); - else if (objeto_que_lleva == OPEN && fl == 177 && flags[14] == 0 && flags[18] == 0) + else if (pickedObject == kVerbOpen && fl == 177 && flags[18] == 1) + talk(346); + else if (pickedObject == kVerbOpen && fl == 177 && flags[14] == 0 && flags[18] == 0) animation_22_2(); - else if (objeto_que_lleva == OPEN && fl == 177 && flags[14] == 1) - abre_puerta(15, 1); - else if (objeto_que_lleva == CLOSE && fl == 177 && flags[14] == 1) - cierra_puerta(15, 1); - else if (objeto_que_lleva == 11 && fl == 50 && flags[22] == 0) { - talk(_text[_lang][347], "347.als"); + else if (pickedObject == kVerbOpen && fl == 177 && flags[14] == 1) + openDoor(15, 1); + else if (pickedObject == kVerbClose && fl == 177 && flags[14] == 1) + closeDoor(15, 1); + else if (pickedObject == 11 && fl == 50 && flags[22] == 0) { + talk(347); flags[29] = 1; - agarra_objeto(23); - resta_objeto(11); + pickObject(23); + removeObject(kItemEarplugs); } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_18(int fl) { - if (objeto_que_lleva == TALK && fl == 55 && flags[36] == 0) +bool DrasculaEngine::room_18(int fl) { + if (pickedObject == kVerbTalk && fl == 55 && flags[36] == 0) animation_24_2(); - else if (objeto_que_lleva == TALK && fl == 55 && flags[36] == 1) - talk(_text[_lang][109], "109.als"); - else if (objeto_que_lleva == LOOK && fl == 181) - talk(_text[_lang][348], "348.als"); - else if (objeto_que_lleva == PICK && fl == 182) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + else if (pickedObject == kVerbTalk && fl == 55 && flags[36] == 1) + talk(109); + else if (pickedObject == kVerbPick && fl == 182) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - copyRect(44, 1, hare_x, hare_y, 41, 70, dir_dibujo2, dir_zona_pantalla); + copyRect(44, 1, curX, curY, 41, 70, drawSurface2, screenSurface); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(4); - agarra_objeto(12); + pickObject(12); visible[2] = 0; flags[28] = 1; - } else if (objeto_que_lleva == LOOK && fl == 182) - talk(_text[_lang][154], "154.als"); - else if (objeto_que_lleva == 8 && fl == 55 && flags[38] == 0 && flags[33] == 1) - talk(_text[_lang][349], "349.als"); - else if (objeto_que_lleva == 13 && fl == 55 && flags[38] == 0 && flags[33] == 1) - talk(_text[_lang][349], "349.als"); - else if (objeto_que_lleva == 15 && fl == 55 && flags[38] == 0 && flags[33] == 1) - talk(_text[_lang][349], "349.als"); - else if (objeto_que_lleva == 16 && fl == 55 && flags[38] == 0 && flags[33] == 1) - talk(_text[_lang][349], "349.als"); - else if (objeto_que_lleva == 17 && fl == 55 && flags[38] == 0 && flags[33] == 1) - talk(_text[_lang][349], "349.als"); - else if (objeto_que_lleva == 8 && fl == 55 && flags[38] == 1 && flags[33] == 1) - animation_24_2(); - else if (objeto_que_lleva == 13 && fl == 55 && flags[38] == 1 && flags[33] == 1) - animation_24_2(); - else if (objeto_que_lleva == 15 && fl == 55 && flags[38] == 1 && flags[33] == 1) - animation_24_2(); - else if (objeto_que_lleva == 16 && fl == 55 && flags[38] == 1 && flags[33] == 1) - animation_24_2(); - else if (objeto_que_lleva == 17 && fl == 55 && flags[38] == 1 && flags[33] == 1) - animation_24_2(); - else if (objeto_que_lleva == 11 && fl == 50 && flags[22] == 0) { - sentido_hare = 3; + } else if (fl == 55 && flags[38] == 0 && flags[33] == 0) { + if (pickedObject == 8 || pickedObject == 13 || pickedObject == 15 || + pickedObject == 16 || pickedObject == 17) + talk(349); + } else if (fl == 55 && flags[38] == 1 && flags[33] == 1) { + if (pickedObject == 8 || pickedObject == 13 || pickedObject == 15 || + pickedObject == 16 || pickedObject == 17) + animation_24_2(); + } + else if (pickedObject == 11 && fl == 50 && flags[22] == 0) { + trackProtagonist = 3; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + updateScreen(); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - copyRect(1, 1, hare_x - 1, hare_y + 3, 42, 67, dir_dibujo2, dir_zona_pantalla); + copyRect(1, 1, curX - 1, curY + 3, 42, 67, drawSurface2, screenSurface); updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(6); - talk(_text[_lang][347], "347.als"); + talk(347); flags[29] = 1; - agarra_objeto(23); - resta_objeto(11); + pickObject(23); + removeObject(kItemEarplugs); } else - hay_respuesta = 0; -} + hasAnswer = 0; -void DrasculaEngine::room_19(int fl) { - if (objeto_que_lleva == LOOK && fl == 214) - talk(_text[_lang][191], "191.als"); - else - hay_respuesta = 0; + return true; } bool DrasculaEngine::room_21(int fl) { - if (objeto_que_lleva == OPEN && fl == 101 && flags[28] == 0) - talk(_text[_lang][419], "419.als"); - else if (objeto_que_lleva == OPEN && fl == 101 && flags[28] == 1) - abre_puerta(0, 1); - else if (objeto_que_lleva == CLOSE && fl == 101) - cierra_puerta(0, 1); - else if(objeto_que_lleva == PICK && fl == 141) { - agarra_objeto(19); + if (pickedObject == kVerbOpen && fl == 101 && flags[28] == 0) + talk(419); + else if (pickedObject == kVerbOpen && fl == 101 && flags[28] == 1) + openDoor(0, 1); + else if (pickedObject == kVerbClose && fl == 101) + closeDoor(0, 1); + else if(pickedObject == kVerbPick && fl == 141) { + pickObject(19); visible[2] = 0; flags[10] = 1; - } else if(objeto_que_lleva == 7 && fl == 101) { + } else if(pickedObject == 7 && fl == 101) { flags[28] = 1; - abre_puerta(0, 1); - sin_verbo(); - } else if (objeto_que_lleva == 21 && fl == 179) { + openDoor(0, 1); + withoutVerb(); + } else if (pickedObject == 21 && fl == 179) { animation_9_4(); return true; } else - hay_respuesta = 0; + hasAnswer = 0; return false; } -void DrasculaEngine::room_22(int fl) { - if (objeto_que_lleva == PICK && fl == 140) - talk(_text[_lang][7], "7.als"); - else if (objeto_que_lleva == 11 && fl == 140) { - agarra_objeto(18); +bool DrasculaEngine::room_22(int fl) { + if (pickedObject == 11 && fl == 140) { + pickObject(18); visible[1] = 0; flags[24] = 1; - } else if (objeto_que_lleva == 22 && fl == 52) { - anima("up.bin",14); + } else if (pickedObject == 22 && fl == 52) { + animate("up.bin",14); flags[26]=1; - comienza_sound("s1.als"); - hipo(14); - fin_sound(); - sin_verbo(); - resta_objeto(22); - actualiza_datos(); - sentido_hare = 3; - talk(_text[_lang][499], "499.als"); - talk(_text[_lang][500], "500.als"); - } else if (objeto_que_lleva == LOOK && fl == 52) - talk(_text[_lang][497], "497.als"); - else if (objeto_que_lleva == TALK && fl == 52) - talk(_text[_lang][498], "498.als"); - else if (objeto_que_lleva == PICK && fl == 180 && flags[26] == 0) - talk(_text[_lang][420], "420.als"); - else if (objeto_que_lleva == PICK && fl == 180 && flags[26] == 1) { - agarra_objeto(7); + playSound(1); + hiccup(14); + finishSound(); + withoutVerb(); + removeObject(22); + updateVisible(); + trackProtagonist = 3; + talk(499); + talk(500); + } else if (pickedObject == kVerbPick && fl == 180 && flags[26] == 0) + talk(420); + else if (pickedObject == kVerbPick && fl == 180 && flags[26] == 1) { + pickObject(7); visible[3] = 0; flags[27] = 1; } else - hay_respuesta = 0; -} - -void DrasculaEngine::room_23(int fl) { - if (objeto_que_lleva == OPEN && fl == 103) { - abre_puerta(0, 0); - actualiza_datos(); - } else if(objeto_que_lleva == CLOSE && fl == 103) { - cierra_puerta(0, 0); - actualiza_datos(); - } else if(objeto_que_lleva == OPEN && fl == 104) - abre_puerta(1, 1); - else if(objeto_que_lleva == CLOSE && fl == 104) - cierra_puerta(1, 1); - else if(objeto_que_lleva == PICK && fl == 142) { - agarra_objeto(8); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_23(int fl) { + if (pickedObject == kVerbOpen && fl == 103) { + openDoor(0, 0); + updateVisible(); + } else if(pickedObject == kVerbClose && fl == 103) { + closeDoor(0, 0); + updateVisible(); + } else if(pickedObject == kVerbOpen && fl == 104) + openDoor(1, 1); + else if(pickedObject == kVerbClose && fl == 104) + closeDoor(1, 1); + else if(pickedObject == kVerbPick && fl == 142) { + pickObject(8); visible[2] = 0; flags[11] = 1; if (flags[22] == 1 && flags[14] == 1) @@ -785,685 +608,502 @@ void DrasculaEngine::room_23(int fl) { if (flags[18] == 1) animation_6_4(); } else - hay_respuesta = 0; -} - -void DrasculaEngine::room_24(int fl) { - if (objeto_que_lleva == OPEN && fl == 105) - abre_puerta(1, 0); - else if (objeto_que_lleva == CLOSE && fl == 105) - cierra_puerta(1, 0); - else if (objeto_que_lleva == OPEN && fl == 106) - abre_puerta(2, 1); - else if (objeto_que_lleva == CLOSE && fl == 106) - cierra_puerta(2, 1); - else if (objeto_que_lleva == LOOK && fl == 151) - talk(_text[_lang][461], "461.als"); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_24(int fl) { + if (pickedObject == kVerbOpen && fl == 105) + openDoor(1, 0); + else if (pickedObject == kVerbClose && fl == 105) + closeDoor(1, 0); + else if (pickedObject == kVerbOpen && fl == 106) + openDoor(2, 1); + else if (pickedObject == kVerbClose && fl == 106) + closeDoor(2, 1); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_26(int fl) { - if (objeto_que_lleva == OPEN && fl == 107 && flags[30] == 0) - abre_puerta(2, 0); - else if (objeto_que_lleva == OPEN && fl == 107 && flags[30] == 1) - talk(_text[_lang][421], "421.als"); - else if (objeto_que_lleva == CLOSE && fl == 107) - cierra_puerta(2, 0); - else if (objeto_que_lleva == 10 && fl == 50 && flags[18] == 1 && flags[12] == 1) +bool DrasculaEngine::room_26(int fl) { + if (pickedObject == kVerbOpen && fl == 107 && flags[30] == 0) + openDoor(2, 0); + else if (pickedObject == kVerbOpen && fl == 107 && flags[30] == 1) + talk(421); + else if (pickedObject == kVerbClose && fl == 107) + closeDoor(2, 0); + else if (pickedObject == 10 && fl == 50 && flags[18] == 1 && flags[12] == 1) animation_5_4(); - else if (objeto_que_lleva == 8 && fl == 50 && flags[18] == 1 && flags[12] == 1) + else if (pickedObject == 8 && fl == 50 && flags[18] == 1 && flags[12] == 1) animation_5_4(); - else if (objeto_que_lleva == 12 && fl == 50 && flags[18] == 1 && flags[12] == 1) + else if (pickedObject == 12 && fl == 50 && flags[18] == 1 && flags[12] == 1) animation_5_4(); - else if (objeto_que_lleva == 16 && fl == 50 && flags[18] == 1 && flags[12] == 1) + else if (pickedObject == 16 && fl == 50 && flags[18] == 1 && flags[12] == 1) animation_5_4(); - else if (objeto_que_lleva == PICK && fl == 143 && flags[18] == 1) { - lleva_al_hare(260, 180); - agarra_objeto(10); + else if (pickedObject == kVerbPick && fl == 143 && flags[18] == 1) { + gotoObject(260, 180); + pickObject(10); visible[1] = 0; flags[12] = 1; - cierra_puerta(2, 0); - sentido_hare = 2; - talk_igorpuerta(_texti[_lang][27], "I27.als"); + closeDoor(2, 0); + trackProtagonist = 2; + talk_igor(27, kIgorDoor); flags[30] = 1; - talk_igorpuerta(_texti[_lang][28], "I28.als"); - lleva_al_hare(153, 180); - } else if (objeto_que_lleva == PICK && fl == 143 && flags[18] == 0) { - lleva_al_hare(260, 180); - copyBackground(80, 78, 199, 94, 38, 27, dir_dibujo3, dir_zona_pantalla); - updateScreen(199, 94, 199, 94, 38, 27, dir_zona_pantalla); + talk_igor(28, kIgorDoor); + gotoObject(153, 180); + } else if (pickedObject == kVerbPick && fl == 143 && flags[18] == 0) { + gotoObject(260, 180); + copyBackground(80, 78, 199, 94, 38, 27, drawSurface3, screenSurface); + updateScreen(199, 94, 199, 94, 38, 27, screenSurface); pause(3); - talk_igor_peluca(_texti[_lang][25], "I25.als"); - lleva_al_hare(153, 180); - } else if (objeto_que_lleva == TALK && fl == 51) + talk_igor(25, kIgorWig); + gotoObject(153, 180); + } else if (pickedObject == kVerbTalk && fl == 51) animation_1_4(); - else if (objeto_que_lleva == OPEN && fl == 167) - talk(_text[_lang][467], "467.als"); - else if (objeto_que_lleva == LOOK && fl == 164) - talk(_text[_lang][470], "470.als"); - else if (objeto_que_lleva == OPEN && fl == 164) - talk(_text[_lang][471], "471.als"); - else if (objeto_que_lleva == LOOK && fl == 163) - talk(_text[_lang][472], "472.als"); - else if (objeto_que_lleva == PICK && fl == 163) - talk(_text[_lang][473], "473.als"); - else if (objeto_que_lleva == LOOK && fl == 165) - talk(_text[_lang][474], "474.als"); - else if (objeto_que_lleva == LOOK && fl == 168) - talk(_text[_lang][476], "476.als"); - else if (objeto_que_lleva == PICK && fl == 168) - talk(_text[_lang][477], "477.als"); else - hay_respuesta = 0; -} - -void DrasculaEngine::room_27(int fl) { - if (objeto_que_lleva == OPEN && fl == 110) - abre_puerta(6, 1); - else if (objeto_que_lleva == CLOSE && fl == 110) - cierra_puerta(6, 1); - else if (objeto_que_lleva == OPEN && fl == 116 && flags[23] == 0) - talk(_text[_lang][419], "419.als"); - else if (objeto_que_lleva == OPEN && fl == 116 && flags[23] == 1) - abre_puerta(5, 3); - else if (objeto_que_lleva == 17 && fl == 116) { + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_27(int fl) { + if (pickedObject == kVerbOpen && fl == 110) + openDoor(6, 1); + else if (pickedObject == kVerbClose && fl == 110) + closeDoor(6, 1); + else if (pickedObject == kVerbOpen && fl == 116 && flags[23] == 0) + talk(419); + else if (pickedObject == kVerbOpen && fl == 116 && flags[23] == 1) + openDoor(5, 3); + else if (pickedObject == 17 && fl == 116) { flags[23] = 1; - abre_puerta(5,3); - sin_verbo(); - } else if (objeto_que_lleva == LOOK && fl == 175) - talk(_text[_lang][429], "429.als"); - else if (fl == 150) - talk(_text[_lang][460], "460.als"); + openDoor(5,3); + withoutVerb(); + } else if (fl == 150) + talk(460); else - hay_respuesta = 0; -} - -void DrasculaEngine::room_29(int fl) { - if (objeto_que_lleva == OPEN && fl == 114) - abre_puerta(4, 1); - else if (objeto_que_lleva == CLOSE && fl == 114) - cierra_puerta(4, 1); - else if (objeto_que_lleva == LOOK && fl == 152) - talk(_text[_lang][463], "463.als"); - else if (objeto_que_lleva == OPEN && fl == 152) - talk(_text[_lang][464], "464.als"); - else if (objeto_que_lleva == LOOK && fl == 153) - talk(_text[_lang][465], "465.als"); - else if (objeto_que_lleva == PICK && fl == 154) - talk(_text[_lang][466], "466.als"); - else if (objeto_que_lleva == OPEN && fl == 156) - talk(_text[_lang][467], "467.als"); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_29(int fl) { + if (pickedObject == kVerbOpen && fl == 114) + openDoor(4, 1); + else if (pickedObject == kVerbClose && fl == 114) + closeDoor(4, 1); else - hay_respuesta = 0; -} - -void DrasculaEngine::room_30(int fl) { - if (objeto_que_lleva == OPEN && fl == 115) - abre_puerta(4, 0); - else if (objeto_que_lleva == CLOSE && fl == 115) - cierra_puerta(4, 0); - else if (objeto_que_lleva == OPEN && fl == 144 && flags[19] == 0) - talk(_text[_lang][422], "422.als"); - else if (objeto_que_lleva == OPEN && fl == 144 && flags[19] == 1 && flags[22] == 1) - abre_puerta(16, 1); - else if (objeto_que_lleva == OPEN && fl == 144 && flags[19] == 1 && flags[22] == 0) { - abre_puerta(16, 1); - talk(_text[_lang][423], "423.als"); + hasAnswer = 0; + + return true; +} + +bool DrasculaEngine::room_30(int fl) { + if (pickedObject == kVerbOpen && fl == 115) + openDoor(4, 0); + else if (pickedObject == kVerbClose && fl == 115) + closeDoor(4, 0); + else if (pickedObject == kVerbOpen && fl == 144 && flags[19] == 0) + talk(422); + else if (pickedObject == kVerbOpen && fl == 144 && flags[19] == 1 && flags[22] == 1) + openDoor(16, 1); + else if (pickedObject == kVerbOpen && fl == 144 && flags[19] == 1 && flags[22] == 0) { + openDoor(16, 1); + talk(423); flags[22] = 1; - agarra_objeto(12); + pickObject(12); if (flags[11] == 1 && flags[14] == 1) flags[18] = 1; if (flags[18] == 1) animation_6_4(); - } else if (objeto_que_lleva == CLOSE && fl == 144) - cierra_puerta(16, 1); - else if (objeto_que_lleva == 13 && fl == 144) { - talk(_text[_lang][424], "424.als"); + } else if (pickedObject == kVerbClose && fl == 144) + closeDoor(16, 1); + else if (pickedObject == 13 && fl == 144) { + talk(424); flags[19] = 1; - } else if (objeto_que_lleva == OPEN && fl == 157) - talk(_text[_lang][468], "468.als"); - else if (objeto_que_lleva == LOOK && fl == 158) - talk(_text[_lang][469], "469.als"); - else - hay_respuesta = 0; + } else + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_31(int fl) { - if (objeto_que_lleva == PICK && fl == 145) { - agarra_objeto(11); +bool DrasculaEngine::room_31(int fl) { + if (pickedObject == kVerbPick && fl == 145) { + pickObject(11); visible[1] = 0; flags[13] = 1; - } else if (objeto_que_lleva == OPEN && fl == 117) - abre_puerta(5, 0); - else if (objeto_que_lleva == CLOSE && fl == 117) - cierra_puerta(5, 0); - else if (objeto_que_lleva == LOOK && fl == 161) - talk(_text[_lang][470], "470.als"); - else if (objeto_que_lleva == OPEN && fl == 161) - talk(_text[_lang][471], "471.als"); + } else if (pickedObject == kVerbOpen && fl == 117) + openDoor(5, 0); + else if (pickedObject == kVerbClose && fl == 117) + closeDoor(5, 0); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_34(int fl) { - if (objeto_que_lleva == MOVE && fl == 146) +bool DrasculaEngine::room_34(int fl) { + if (pickedObject == kVerbMove && fl == 146) animation_8_4(); - else if (objeto_que_lleva == LOOK && fl == 146) - talk(_text[_lang][458], "458.als"); - else if (objeto_que_lleva == PICK && fl == 146) - talk(_text[_lang][459], "459.als"); - else if (objeto_que_lleva == OPEN && fl == 120 && flags[25] == 1) - abre_puerta(8, 2); - else if (objeto_que_lleva == OPEN && fl == 120 && flags[25] == 0) { - abre_puerta(8, 2); - sentido_hare = 3; - talk(_text[_lang][425], "425.als"); - agarra_objeto(14); + else if (pickedObject == kVerbOpen && fl == 120 && flags[25] == 1) + openDoor(8, 2); + else if (pickedObject == kVerbOpen && fl == 120 && flags[25] == 0) { + openDoor(8, 2); + trackProtagonist = 3; + talk(425); + pickObject(14); flags[25] = 1; - } else if (objeto_que_lleva == CLOSE && fl == 120) - cierra_puerta(8, 2); + } else if (pickedObject == kVerbClose && fl == 120) + closeDoor(8, 2); else - hay_respuesta=0; + hasAnswer=0; + + return true; } -void DrasculaEngine::room_35(int fl) { - if (objeto_que_lleva == PICK && fl == 148) { - agarra_objeto(16); +bool DrasculaEngine::room_35(int fl) { + if (pickedObject == kVerbPick && fl == 148) { + pickObject(16); visible[2] = 0; flags[14] = 1; if (flags[11] == 1 && flags[22] == 1) flags[18] = 1; if (flags[18] == 1) animation_6_4(); - } else if (objeto_que_lleva == PICK && fl == 147) { - talk(_text[_lang][426], "426.als"); - agarra_objeto(15); + } else if (pickedObject == kVerbPick && fl == 147) { + talk(426); + pickObject(15); visible[1] = 0; flags[15] = 1; flags[17] = 1; - actualiza_datos(); - } else if (objeto_que_lleva == PICK && fl == 149) { - agarra_objeto(13); + updateVisible(); + } else if (pickedObject == kVerbPick && fl == 149) { + pickObject(13); visible[3] = 0; flags[17] = 0; } else - hay_respuesta = 0; -} + hasAnswer = 0; -void DrasculaEngine::room_44(int fl) { - if (objeto_que_lleva == LOOK && fl == 172) - talk(_text[_lang][428], "428.als"); - else - hay_respuesta = 0; + return true; } -void DrasculaEngine::room_49(int fl){ - if (objeto_que_lleva == TALK && fl ==51) - conversa("op_9.cal"); - else if (objeto_que_lleva == LOOK && fl == 51) - talk(_text[_lang][132], "132.als"); - else if ((objeto_que_lleva == 8 && fl == 51) || (objeto_que_lleva == 8 && fl == 203)) +bool DrasculaEngine::room_49(int fl) { + if (pickedObject == kVerbTalk && fl ==51) + converse(9); + else if ((pickedObject == 8 && fl == 51) || (pickedObject == 8 && fl == 203)) animation_5_5(); - else if (objeto_que_lleva == LOOK && fl == 200) - talk(_text[_lang][133], "133.als"); - else if (objeto_que_lleva == TALK && fl == 200) - talk(_text[_lang][134], "134.als"); - else if (objeto_que_lleva == LOOK && fl == 201) - talk(_text[_lang][135], "135.als"); - else if (objeto_que_lleva == LOOK && fl == 203) - talk(_text[_lang][137], "137.als"); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_53(int fl) { - if (objeto_que_lleva == PICK && fl == 120) { - agarra_objeto(16); +bool DrasculaEngine::room_53(int fl) { + if (pickedObject == kVerbPick && fl == 120) { + pickObject(16); visible[3] = 0; - } else if (objeto_que_lleva == LOOK && fl == 121) - talk(_text[_lang][128], "128.als"); - else if (objeto_que_lleva == LOOK && fl == 209) - talk(_text[_lang][129], "129.als"); - else if (objeto_que_lleva == MOVE && fl == 123) + } else if (pickedObject == kVerbMove && fl == 123) animation_11_5(); - else if (objeto_que_lleva == LOOK && fl == 52) - talk(_text[_lang][447], "447.als"); - else if (objeto_que_lleva == TALK && fl == 52) - talk(_text[_lang][131], "131.als"); - else if (objeto_que_lleva == 12 && fl == 52) + else if (pickedObject == 12 && fl == 52) animation_10_5(); - else if (objeto_que_lleva == 15 && fl == 52) + else if (pickedObject == 15 && fl == 52) animation_9_5(); - else if (objeto_que_lleva == 16 && fl == 121) { + else if (pickedObject == 16 && fl == 121) { flags[2] = 1; - sin_verbo(); - actualiza_datos(); - } else if (objeto_que_lleva == 16) { - talk(_text[_lang][439], "439.als"); - sin_verbo(); + withoutVerb(); + updateVisible(); + } else if (pickedObject == 16) { + talk(439); + withoutVerb(); visible[3] = 1; } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_54(int fl) { - if ((objeto_que_lleva == TALK && fl == 118) || (objeto_que_lleva == LOOK && fl == 118 && flags[0] == 0)) +bool DrasculaEngine::room_54(int fl) { + if ((pickedObject == kVerbTalk && fl == 118) || (pickedObject == kVerbLook && fl == 118 && flags[0] == 0)) animation_1_5(); - else if (objeto_que_lleva == LOOK && fl == 118 && flags[0]==1) - talk(_text[_lang][124], "124.als"); - else if (objeto_que_lleva == LOOK && fl == 53) - talk(_text[_lang][127], "127.als"); - else if (objeto_que_lleva == TALK && fl == 53 && flags[14] == 0) { - talk(_text[_lang][288], "288.als"); + else if (pickedObject == kVerbLook && fl == 118 && flags[0] == 1) + talk(124); + else if (pickedObject == kVerbTalk && fl == 53 && flags[14] == 0) { + talk(288); flags[12] = 1; pause(10); - talk_mus(_texte[_lang][1], "E1.als"); - talk(_text[_lang][289], "289.als"); - talk_mus(_texte[_lang][2], "E2.als"); - talk_mus(_texte[_lang][3], "E3.als"); - conversa("op_10.cal"); + talk_mus(1); + talk(289); + talk_mus(2); + talk_mus(3); + converse(10); flags[12] = 0; flags[14] = 1; - } else if (objeto_que_lleva == TALK && fl == 53 && flags[14] == 1) - talk(_text[_lang][109], "109.als"); - else if (objeto_que_lleva == PICK && fl == 9999 && flags[13] == 0) { - agarra_objeto(8); + } else if (pickedObject == kVerbTalk && fl == 53 && flags[14] == 1) + talk(109); + else if (pickedObject == kVerbPick && fl == 9999 && flags[13] == 0) { + pickObject(8); flags[13] = 1; - talk_mus(_texte[_lang][10], "e10.als"); - actualiza_datos(); - } else if (objeto_que_lleva == OPEN && fl == 119) - talk(_text[_lang][125], "125.als"); - else if (objeto_que_lleva == LOOK && fl == 119) - talk(_text[_lang][126], "126.als"); - else if (objeto_que_lleva == 10 && fl == 119) { + talk_mus(10); + updateVisible(); + } else if (pickedObject == 10 && fl == 119) { pause(4); - talk(_text[_lang][436], "436.als"); - sin_verbo(); - resta_objeto(10); + talk(436); + withoutVerb(); + removeObject(10); } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_55(int fl) { - if (objeto_que_lleva == PICK && fl == 122) { - agarra_objeto(12); +bool DrasculaEngine::room_55(int fl) { + if (pickedObject == kVerbPick && fl == 122) { + pickObject(12); flags[8] = 1; - actualiza_datos(); - } else if (objeto_que_lleva == LOOK && fl == 122) - talk(_text[_lang][138], "138.als"); - else if (objeto_que_lleva == LOOK && fl == 204) - talk(_text[_lang][139], "139.als"); - else if (objeto_que_lleva == LOOK && fl == 205) - talk(_text[_lang][140], "140.als"); - else if (fl == 206) { - comienza_sound("s11.als"); - anima("det.bin", 17); - fin_sound(); - lleva_al_hare(hare_x - 3, hare_y + alto_hare + 6); + updateVisible(); + } else if (fl == 206) { + playSound(11); + animate("det.bin", 17); + finishSound(); + gotoObject(curX - 3, curY + curHeight + 6); } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } bool DrasculaEngine::room_56(int fl) { - if (objeto_que_lleva == OPEN && fl == 124) { + if (pickedObject == kVerbOpen && fl == 124) { animation_14_5(); return true; - } else if (objeto_que_lleva == LOOK && fl == 124) - talk(_text[_lang][450], "450.als"); - else if (objeto_que_lleva == OPEN && fl == 207) - talk(_text[_lang][141], "141.als"); - else if (objeto_que_lleva == LOOK && fl == 208) - talk(_text[_lang][142], "142.als"); - else - hay_respuesta = 0; + } else + hasAnswer = 0; return false; } -void DrasculaEngine::room_58(int fl) { - if (objeto_que_lleva == MOVE && fl == 103) +bool DrasculaEngine::room_58(int fl) { + if (pickedObject == kVerbMove && fl == 103) animation_7_6(); - else if (objeto_que_lleva == LOOK && fl == 104) - talk(_text[_lang][454], "454.als"); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_59(int fl) { - if ((objeto_que_lleva == TALK && fl == 51) || (objeto_que_lleva == LOOK && fl == 51)) { +bool DrasculaEngine::room_59(int fl) { + if ((pickedObject == kVerbTalk && fl == 51) || (pickedObject == kVerbLook && fl == 51)) { flags[9] = 1; - talk(_text[_lang][259], "259.als"); - talk_bj_cama(_textbj[_lang][13], "bj13.als"); - talk(_text[_lang][263], "263.als"); - talk_bj_cama(_textbj[_lang][14], "bj14.als"); + talk(259); + talk_bj_bed(13); + talk(263); + talk_bj_bed(14); pause(40); - talk(_text[_lang][264], "264.als"); - talk_bj_cama(_textbj[_lang][15], "BJ15.als"); - talk(_text[_lang][265], "265.als"); + talk(264); + talk_bj_bed(15); + talk(265); flags[9] = 0; if (flags[11] == 0) { - comienza_sound("s12.als"); + playSound(12); delay(40); - fin_sound(); + finishSound(); delay(10); - lleva_al_hare(174, 168); - sentido_hare = 2; + gotoObject(174, 168); + trackProtagonist = 2; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); pause(40); - comienza_sound("s12.als"); + playSound(12); pause(19); - fin_sound_corte(); + stopSound(); hare_se_ve = 0; updateRoom(); - copyRect(101, 34, hare_x - 4, hare_y - 1, 37, 70, dir_dibujo3, dir_zona_pantalla); - copyBackground(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyRect(101, 34, curX - 4, curY - 1, 37, 70, drawSurface3, screenSurface); + copyBackground(0, 0, 0, 0, 320, 200, screenSurface, bgSurface); + updateScreen(); hare_se_ve = 1; clearRoom(); - loadPic("tlef0.alg"); - decompressPic(dir_dibujo1, COMPLETA); - loadPic("tlef1.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("tlef2.alg"); - decompressPic(dir_hare_frente, 1); - loadPic("tlef3.alg"); - decompressPic(dir_hare_fondo, 1); - talk_htel(_text[_lang][240], "240.als"); - - color_abc(VON_BRAUN); + loadPic("tlef0.alg", bgSurface, COMPLETE_PAL); + loadPic("tlef1.alg", drawSurface3); + loadPic("tlef2.alg", frontSurface); + loadPic("tlef3.alg", backSurface); + talk_htel(240); + + color_abc(kColorBrown); talk_solo(_textvb[_lang][58], "VB58.als"); - talk_htel(_text[_lang][241], "241.als"); - color_abc(VON_BRAUN); + talk_htel(241); + color_abc(kColorBrown); talk_solo(_textvb[_lang][59], "VB59.als"); - talk_htel(_text[_lang][242], "242.als"); - color_abc(VON_BRAUN); + talk_htel(242); + color_abc(kColorBrown); talk_solo(_textvb[_lang][60], "VB60.als"); - talk_htel(_text[_lang][196], "196.als"); - color_abc(VON_BRAUN); + talk_htel(196); + color_abc(kColorBrown); talk_solo(_textvb[_lang][61],"VB61.als"); - talk_htel(_text[_lang][244], "244.als"); - color_abc(VON_BRAUN); + talk_htel(244); + color_abc(kColorBrown); talk_solo(_textvb[_lang][62], "VB62.als"); clearRoom(); - loadPic("aux59.alg"); - decompressPic(dir_dibujo3, 1); - loadPic("96.alg"); - decompressPic(dir_hare_frente, COMPLETA); - loadPic("99.alg"); - decompressPic(dir_hare_fondo, 1); - loadPic("59.alg"); - decompressPic(dir_dibujo1, MEDIA); - sentido_hare = 3; - talk(_text[_lang][245], "245.als"); - sin_verbo(); + loadPic("aux59.alg", drawSurface3); + loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(99, backSurface); + loadPic(59, bgSurface, HALF_PAL); + trackProtagonist = 3; + talk(245); + withoutVerb(); flags[11] = 1; } } else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } bool DrasculaEngine::room_60(int fl) { - if (objeto_que_lleva == MOVE && fl == 112) + if (pickedObject == kVerbMove && fl == 112) animation_10_6(); - else if (objeto_que_lleva == LOOK && fl == 112) - talk(_text[_lang][440], "440.als"); - else if (objeto_que_lleva == TALK && fl == 52) { - talk(_text[_lang][266], "266.als"); - talk_taber2(_textt[_lang][1], "t1.als"); - conversa("op_12.cal"); - sin_verbo(); - objeto_que_lleva = 0; - } else if (objeto_que_lleva == TALK && fl == 115) - talk(_text[_lang][455], "455.als"); - else if (objeto_que_lleva == TALK && fl == 56) - talk(_text[_lang][455], "455.als"); - else if (objeto_que_lleva == LOOK && fl == 114) - talk(_text[_lang][167], "167.als"); - else if (objeto_que_lleva == LOOK && fl == 113) - talk(_text[_lang][168], "168.als"); - else if (objeto_que_lleva == PICK && fl == 113) - talk(_text[_lang][170], "170.als"); - else if (objeto_que_lleva == MOVE && fl == 113) - talk(_text[_lang][170], "170.als"); - else if (objeto_que_lleva == TALK && fl == 113) - talk(_text[_lang][169], "169.als"); - else if (objeto_que_lleva == 21 && fl == 56) + else if (pickedObject == kVerbTalk && fl == 52) { + talk(266); + talk_bartender(1, 1); + converse(12); + withoutVerb(); + pickedObject = 0; + } else if (pickedObject == 21 && fl == 56) animation_18_6(); - else if (objeto_que_lleva == 9 && fl == 56 && flags[6] == 1) { + else if (pickedObject == 9 && fl == 56 && flags[6] == 1) { animation_9_6(); return true; - } else if (objeto_que_lleva == 9 && fl == 56 && flags[6] == 0) { - anima("cnf.bin", 14); - talk(_text[_lang][455], "455.als"); + } else if (pickedObject == 9 && fl == 56 && flags[6] == 0) { + animate("cnf.bin", 14); + talk(455); } else - hay_respuesta = 0; + hasAnswer = 0; return false; } -void DrasculaEngine::room_61(int fl) { - if (objeto_que_lleva == LOOK && fl == 116) - talk(_text[_lang][172], "172.als"); - else if (objeto_que_lleva == LOOK && fl == 117) - talk(_text[_lang][173], "173.als"); - else if (objeto_que_lleva == MOVE && fl == 117) - talk(_text[_lang][174], "174.als"); - else if (objeto_que_lleva == OPEN && fl == 117) - talk(_text[_lang][174], "174.als"); - else - hay_respuesta = 0; -} - -void DrasculaEngine::room_62(int fl) { - if (objeto_que_lleva == TALK && fl == 53) - conversa("op_13.cal"); - else if (objeto_que_lleva == TALK && fl == 52 && flags[0] == 0) +bool DrasculaEngine::room_62(int fl) { + if (pickedObject == kVerbTalk && fl == 53) + converse(13); + else if (pickedObject == kVerbTalk && fl == 52 && flags[0] == 0) animation_3_1(); - else if (objeto_que_lleva == TALK && fl == 52 && flags[0] == 1) - talk(_text[_lang][109], "109.als"); - else if (objeto_que_lleva == TALK && fl == 54) + else if (pickedObject == kVerbTalk && fl == 52 && flags[0] == 1) + talk(109); + else if (pickedObject == kVerbTalk && fl == 54) animation_4_1(); - else if (objeto_que_lleva == LOOK && fl == 100) - talk(_text[_lang][168], "168.als"); - else if (objeto_que_lleva == TALK && fl == 100) - talk(_text[_lang][169], "169.als"); - else if (objeto_que_lleva == PICK && fl == 100) - talk(_text[_lang][170], "170.als"); - else if (objeto_que_lleva == LOOK && fl == 101) - talk(_text[_lang][171], "171.als"); - else if (objeto_que_lleva == LOOK && fl == 102) - talk(_text[_lang][167], "167.als"); - else if (objeto_que_lleva == LOOK && fl == 103) - talk(_text[_lang][166], "166.als"); - else hay_respuesta = 0; -} - -void DrasculaEngine::room_63(int fl) { - if (objeto_que_lleva == LOOK && fl == 110) - talk(_text[_lang][172], "172.als"); - else if (objeto_que_lleva == LOOK && fl == 109) - talk(_text[_lang][173], "173.als"); - else if (objeto_que_lleva == MOVE && fl == 109) - talk(_text[_lang][174], "174.als"); - else if (objeto_que_lleva == LOOK && fl == 108) - talk(_text[_lang][334], "334.als"); - else if (objeto_que_lleva == TALK && fl == 108) - talk(_text[_lang][333], "333.als"); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } -void DrasculaEngine::room_pendulo(int fl) { - if (objeto_que_lleva == LOOK && fl == 100) - talk(_text[_lang][452], "452.als"); - else if (objeto_que_lleva == LOOK && fl == 101) - talk (_text[_lang][123], "123.als"); - else if (objeto_que_lleva == PICK && fl == 101) - agarra_objeto(20); - else if (objeto_que_lleva == 20 && fl == 100) +bool DrasculaEngine::room_102(int fl) { + if (pickedObject == kVerbPick && fl == 101) + pickObject(20); + else if (pickedObject == 20 && fl == 100) animation_6_6(); - else if (objeto_que_lleva == PICK || objeto_que_lleva == OPEN) - talk(_text[_lang][453], "453.als"); + else if (pickedObject == kVerbPick || pickedObject == kVerbOpen) + talk(453); else - hay_respuesta = 0; + hasAnswer = 0; + + return true; } void DrasculaEngine::updateRefresh() { - if (num_ejec == 1) { - if (!strcmp(num_room, "63.alg")) - update_63(); - else if (!strcmp(num_room, "62.alg")) - update_62(); - } else if (num_ejec == 2) { - if (!strcmp(num_room, "3.alg")) - update_3(); - else if (!strcmp(num_room, "2.alg")) - update_2(); - else if (!strcmp(num_room, "4.alg")) - update_4(); - else if (!strcmp(num_room, "5.alg")) - update_5(); - else if (!strcmp(num_room, "15.alg")) - update_15(); - else if (!strcmp(num_room, "17.alg")) - update_17(); - else if (!strcmp(num_room, "18.alg")) - update_18(); - else if (!strcmp(num_room, "10.alg")) - mapa(); - } else if (num_ejec == 3) { - if (!strcmp(num_room, "20.alg")) - update_20(); - else if (!strcmp(num_room, "13.alg")) - update_13(); - } else if (num_ejec == 4) { - if (!strcmp(num_room, "29.alg")) - update_29(); - else if (!strcmp(num_room, "26.alg")) - update_26(); - else if (!strcmp(num_room, "27.alg")) - update_27(); - else if (!strcmp(num_room, "31.alg")) - update_31(); - else if (!strcmp(num_room, "34.alg")) - update_34(); - else if (!strcmp(num_room, "35.alg")) - update_35(); - } else if (num_ejec == 5) { - if (!strcmp(num_room, "45.alg")) - mapa(); - else if (!strcmp(num_room, "50.alg")) - update_50(); - else if (!strcmp(num_room, "57.alg")) - update_57(); - } else if (num_ejec == 6) { - if (!strcmp(num_room, "60.alg")) - update_60(); - else if (!strcmp(num_room, "61.alg")) - update_61(); - else if (!strcmp(num_room, "58.alg")) - update_58(); + // Check generic updaters + for (int i = 0; i < _roomUpdatesSize; i++) { + if (_roomUpdates[i].roomNum == roomNumber) { + if (_roomUpdates[i].flag < 0 || + flags[_roomUpdates[i].flag] == _roomUpdates[i].flagValue) { + if (_roomUpdates[i].type == 0) { + copyBackground(_roomUpdates[i].sourceX, _roomUpdates[i].sourceY, + _roomUpdates[i].destX, _roomUpdates[i].destY, + _roomUpdates[i].width, _roomUpdates[i].height, + drawSurface3, screenSurface); + } else { + copyRect(_roomUpdates[i].sourceX, _roomUpdates[i].sourceY, + _roomUpdates[i].destX, _roomUpdates[i].destY, + _roomUpdates[i].width, _roomUpdates[i].height, + drawSurface3, screenSurface); + } + } + } } + + // Call room-specific updater + char rm[20]; + sprintf(rm, "update_%d", roomNumber); + for (uint i = 0; i < _roomUpdaters.size(); i++) { + if (!strcmp(rm, _roomUpdaters[i]->desc)) { + debug(4, "Calling room updater %d", roomNumber); + (this->*(_roomUpdaters[i]->proc))(); + break; + } + } + + if (roomNumber == 10) + showMap(); + else if (roomNumber == 45) + showMap(); } void DrasculaEngine::updateRefresh_pre() { - if (num_ejec == 1) { - if (!strcmp(num_room, "62.alg")) - update_62_pre(); - else if (!strcmp(num_room, "16.alg")) - pon_bj(); - } else if (num_ejec == 2) { - if (!strcmp(num_room, "1.alg")) - update_1_pre(); - else if (!strcmp(num_room, "3.alg")) - update_3_pre(); - else if (!strcmp(num_room, "5.alg")) - update_5_pre(); - else if (!strcmp(num_room, "6.alg")) - update_6_pre(); - else if (!strcmp(num_room, "7.alg")) - update_7_pre(); - else if (!strcmp(num_room, "9.alg")) - update_9_pre(); - else if (!strcmp(num_room, "12.alg")) - update_12_pre(); - else if (!strcmp(num_room, "14.alg")) - update_14_pre(); - else if (!strcmp(num_room, "16.alg")) - update_16_pre(); - else if (!strcmp(num_room, "17.alg")) - update_17_pre(); - else if (!strcmp(num_room, "18.alg")) - update_18_pre(); - } else if (num_ejec == 3) { - // nothing - } else if (num_ejec == 4) { - if (!strcmp(num_room, "21.alg")) - update_21_pre(); - else if (!strcmp(num_room, "22.alg")) - update_22_pre(); - else if (!strcmp(num_room, "23.alg")) - update_23_pre(); - else if (!strcmp(num_room, "24.alg")) - update_24_pre(); - else if (!strcmp(num_room, "26.alg")) - update_26_pre(); - else if (!strcmp(num_room, "27.alg")) - update_27_pre(); - else if (!strcmp(num_room, "29.alg")) - update_29_pre(); - else if (!strcmp(num_room, "30.alg")) - update_30_pre(); - else if (!strcmp(num_room, "31.alg")) - update_31_pre(); - else if (!strcmp(num_room, "34.alg")) - update_34_pre(); - else if (!strcmp(num_room, "35.alg")) - update_35_pre(); - } else if (num_ejec == 5) { - if (!strcmp(num_room,"49.alg")) - update_49_pre(); - else if (!strcmp(num_room,"53.alg")) - update_53_pre(); - else if (!strcmp(num_room,"54.alg")) - update_54_pre(); - else if (!strcmp(num_room,"56.alg")) - update_56_pre(); - } else if (num_ejec == 6) { - if (!strcmp(num_room, "102.alg")) - update_pendulo(); - else if (!strcmp(num_room, "58.alg")) - update_58_pre(); - else if (!strcmp(num_room, "59.alg")) - update_59_pre(); - else if (!strcmp(num_room, "60.alg")) - update_60_pre(); + // Check generic preupdaters + for (int i = 0; i < _roomPreUpdatesSize; i++) { + if (_roomPreUpdates[i].roomNum == roomNumber) { + if (_roomPreUpdates[i].flag < 0 || + flags[_roomPreUpdates[i].flag] == _roomPreUpdates[i].flagValue) { + if (_roomPreUpdates[i].type == 0) { + copyBackground(_roomPreUpdates[i].sourceX, _roomPreUpdates[i].sourceY, + _roomPreUpdates[i].destX, _roomPreUpdates[i].destY, + _roomPreUpdates[i].width, _roomPreUpdates[i].height, + drawSurface3, screenSurface); + } else { + copyRect(_roomPreUpdates[i].sourceX, _roomPreUpdates[i].sourceY, + _roomPreUpdates[i].destX, _roomPreUpdates[i].destY, + _roomPreUpdates[i].width, _roomPreUpdates[i].height, + drawSurface3, screenSurface); + } + } + } } -} -void DrasculaEngine::update_1_pre() { - int cambio_col_antes = cambio_de_color; + // Call room-specific preupdater + char rm[20]; + sprintf(rm, "update_%d_pre", roomNumber); + for (uint i = 0; i < _roomPreupdaters.size(); i++) { + if (!strcmp(rm, _roomPreupdaters[i]->desc)) { + debug(4, "Calling room preupdater %d", roomNumber); + (this->*(_roomPreupdaters[i]->proc))(); + break; + } + } - if (hare_x > 98 && hare_x < 153) - cambio_de_color = 1; - else - cambio_de_color = 0; + if (currentChapter == 1 && roomNumber == 16) + placeBJ(); +} - if (cambio_col_antes != cambio_de_color && cambio_de_color == 1) - hare_oscuro(); - if (cambio_col_antes != cambio_de_color && cambio_de_color == 0) - hare_claro(); +void DrasculaEngine::update_1_pre() { + if (curX > 98 && curX < 153) { + changeColor = 1; + setDarkPalette(); + } else { + changeColor = 0; + setBrightPalette(); + } if (flags[8] == 0) - copyBackground(2, 158, 208, 67, 27, 40, dir_dibujo3, dir_zona_pantalla); + copyBackground(2, 158, 208, 67, 27, 40, drawSurface3, screenSurface); } -void DrasculaEngine::update_2(){ - int pos_murci[6]; - int diferencia; - int murci_x[] = {0, 38, 76, 114, 152, 190, 228, 266, +void DrasculaEngine::update_2() { + int batPos[6]; + int difference; + int batX[] = {0, 38, 76, 114, 152, 190, 228, 266, 0, 38, 76, 114, 152, 190, 228, 266, 0, 38, 76, 114, 152, 190, 0, 48, 96, 144, 192, 240, @@ -1471,7 +1111,7 @@ void DrasculaEngine::update_2(){ 88, 146, 204, 262, 88, 146, 204, 262}; - int murci_y[] = {179, 179, 179, 179, 179, 179, 179, 179, + int batY[] = {179, 179, 179, 179, 179, 179, 179, 179, 158, 158, 158, 158, 158, 158, 158, 158, 137, 137, 137, 137, 137, 137, 115, 115, 115, 115, 115, 115, @@ -1479,557 +1119,959 @@ void DrasculaEngine::update_2(){ 41, 41, 41, 41, 4, 4, 4, 4}; - if (frame_murcielago == 41) - frame_murcielago = 0; + if (actorFrames[kFrameBat] == 41) + actorFrames[kFrameBat] = 0; - pos_murci[0] = murci_x[frame_murcielago]; - pos_murci[1] = murci_y[frame_murcielago]; + batPos[0] = batX[actorFrames[kFrameBat]]; + batPos[1] = batY[actorFrames[kFrameBat]]; - if (frame_murcielago < 22) { - pos_murci[4] = 37; - pos_murci[5] = 21; - } else if (frame_murcielago > 27) { - pos_murci[4] = 57; - pos_murci[5] = 36; + if (actorFrames[kFrameBat] < 22) { + batPos[4] = 37; + batPos[5] = 21; + } else if (actorFrames[kFrameBat] > 27) { + batPos[4] = 57; + batPos[5] = 36; } else { - pos_murci[4] = 47; - pos_murci[5] = 22; + batPos[4] = 47; + batPos[5] = 22; } - pos_murci[2] = 239; - pos_murci[3] = 19; + batPos[2] = 239; + batPos[3] = 19; - copyRectClip(pos_murci, dir_dibujo3, dir_zona_pantalla); - diferencia = vez() - conta_ciego_vez; - if (diferencia >= 6) { - frame_murcielago++; - conta_ciego_vez = vez(); + copyRectClip(batPos, drawSurface3, screenSurface); + difference = getTime() - savedTime; + if (difference >= 6) { + actorFrames[kFrameBat]++; + savedTime = getTime(); } - copyRect(29, 37, 58, 114, 57, 39, dir_dibujo3, dir_zona_pantalla); - mapa(); -} - -void DrasculaEngine::update_3_pre() { - if (flags[3] == 1) - copyBackground(258, 110, 85, 44, 23, 53, dir_dibujo3, dir_zona_pantalla); + copyRect(29, 37, 58, 114, 57, 39, drawSurface3, screenSurface); + showMap(); } void DrasculaEngine::update_3() { - if (hare_y + alto_hare < 118) - copyRect(129, 110, 194, 36, 126, 88, dir_dibujo3, dir_zona_pantalla); - copyRect(47, 57, 277, 143, 43, 50, dir_dibujo3, dir_zona_pantalla); + if (curY + curHeight < 118) + copyRect(129, 110, 194, 36, 126, 88, drawSurface3, screenSurface); + copyRect(47, 57, 277, 143, 43, 50, drawSurface3, screenSurface); } void DrasculaEngine::update_4() { - int cambio_col_antes = cambio_de_color; - if (hare_x > 190) - cambio_de_color = 1; - else - cambio_de_color = 0; - - if (cambio_col_antes != cambio_de_color && cambio_de_color == 1) - hare_oscuro(); - if (cambio_col_antes != cambio_de_color && cambio_de_color == 0) - hare_claro(); -} - -void DrasculaEngine::update_5_pre(){ - if (flags[8] == 0) - copyBackground(256, 152, 208, 67, 27, 40, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_5() { - copyRect(114, 130, 211, 87, 109, 69, dir_dibujo3, dir_zona_pantalla); + if (curX > 190) { + changeColor = 1; + setDarkPalette(); + } else { + changeColor = 0; + setBrightPalette(); + } } void DrasculaEngine::update_6_pre() { - int cambio_col_antes = cambio_de_color; - - if ((hare_x > 149 && hare_y + alto_hare > 160 && hare_x < 220 && hare_y + alto_hare < 188) || - (hare_x > 75 && hare_y + alto_hare > 183 && hare_x < 145)) - cambio_de_color = 0; - else - cambio_de_color = 1; - - if (cambio_col_antes != cambio_de_color && cambio_de_color == 1) - hare_oscuro(); - if (cambio_col_antes != cambio_de_color && cambio_de_color == 0) - hare_claro(); - - if (flags[1] == 0) - copyBackground(97, 117, 34, 148, 36, 31, dir_dibujo3, dir_zona_pantalla); - if (flags[0] == 0) - copyBackground(3, 103, 185, 69, 23, 76, dir_dibujo3, dir_zona_pantalla); - if (flags[2] == 0) - copyBackground(28, 100, 219, 72, 64, 97, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_7_pre() { - if (flags[35] == 0) - copyBackground(1, 72, 158, 162, 19, 12, dir_dibujo3, dir_zona_pantalla); + if ((curX > 149 && curY + curHeight > 160 && curX < 220 && curY + curHeight < 188) || + (curX > 75 && curY + curHeight > 183 && curX < 145)) { + changeColor = 0; + setBrightPalette(); + } else { + changeColor = 1; + setDarkPalette(); + } } void DrasculaEngine::update_9_pre() { - int ciego_x[] = {26, 68, 110, 152, 194, 236, 278, 26, 68}; - int ciego_y[] = {51, 51, 51, 51, 51, 51, 51, 127, 127}; - int diferencia; + int blindX[] = {26, 68, 110, 152, 194, 236, 278, 26, 68}; + int blindY[] = {51, 51, 51, 51, 51, 51, 51, 127, 127}; + int difference; - copyRect(ciego_x[frame_ciego], ciego_y[frame_ciego], 122, 57, 41, 72, dir_dibujo3, dir_zona_pantalla); + copyRect(blindX[actorFrames[kFrameBlind]], blindY[actorFrames[kFrameBlind]], + 122, 57, 41, 72, drawSurface3, screenSurface); if (flags[9] == 0) { - diferencia = vez() - conta_ciego_vez; - if (diferencia >= 11) { - frame_ciego++; - conta_ciego_vez = vez(); + difference = getTime() - savedTime; + if (difference >= 11) { + actorFrames[kFrameBlind]++; + savedTime = getTime(); } - if (frame_ciego == 9) - frame_ciego = 0; + if (actorFrames[kFrameBlind] == 9) + actorFrames[kFrameBlind] = 0; } else - frame_ciego = 3; -} - -void DrasculaEngine::update_12_pre() { - if (flags[16] == 0) - copyBackground(1, 131, 106, 117, 55, 68, dir_dibujo3, dir_zona_pantalla); + actorFrames[kFrameBlind] = 3; } void DrasculaEngine::update_13() { - if (hare_x > 55 && flags[3] == 0) + if (curX > 55 && flags[3] == 0) animation_6_3(); + // These cannot be placed in an array, as they're between screen updates if (flags[1] == 0) - copyRect(185, 110, 121, 65, 67, 88, dir_dibujo3, dir_zona_pantalla); + copyRect(185, 110, 121, 65, 67, 88, drawSurface3, screenSurface); if (flags[2] == 0) - copyRect(185, 21, 121, 63, 67, 88, dir_dibujo3, dir_zona_pantalla); - copyRect(3, 127, 99, 102, 181, 71, dir_dibujo3, dir_zona_pantalla); + copyRect(185, 21, 121, 63, 67, 88, drawSurface3, screenSurface); + copyRect(3, 127, 99, 102, 181, 71, drawSurface3, screenSurface); } void DrasculaEngine::update_14_pre() { - int velas_y[] = {158, 172, 186}; - int cirio_x[] = {14, 19, 24}; - int pianista_x[] = {1, 91, 61, 31, 91, 31, 1, 61, 31}; - int borracho_x[] = {1, 42, 83, 124, 165, 206, 247, 1}; - int diferencia; - - copyBackground(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla); - copyBackground(cirio_x[frame_velas], 146, 311, 80, 4, 8, dir_dibujo3, dir_zona_pantalla); - - if (parpadeo == 5) - copyBackground(1, 149, 127, 52, 9, 5, dir_dibujo3, dir_zona_pantalla); - if (hare_x > 101 && hare_x < 155) - copyBackground(31, 138, 178, 51, 18, 16, dir_dibujo3, dir_zona_pantalla); + int difference; + + copyBackground(123, _candleY[actorFrames[kFrameCandles]], 142, 14, 39, 13, drawSurface3, screenSurface); + copyBackground(_candleX[actorFrames[kFrameCandles]], 146, 311, 80, 4, 8, drawSurface3, screenSurface); + + if (blinking == 5) + copyBackground(1, 149, 127, 52, 9, 5, drawSurface3, screenSurface); + if (curX > 101 && curX < 155) + copyBackground(31, 138, 178, 51, 18, 16, drawSurface3, screenSurface); if (flags[11] == 0) - copyBackground(pianista_x[frame_piano], 157, 245, 130, 29, 42, dir_dibujo3, dir_zona_pantalla); + copyBackground(_pianistX[actorFrames[kFramePianist]], 157, 245, 130, 29, 42, drawSurface3, screenSurface); else if (flags[5] == 0) - copyBackground(145, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); + copyBackground(145, 139, 228, 112, 47, 60, extraSurface, screenSurface); else - copyBackground(165, 140, 229, 117, 43, 59, dir_dibujo3, dir_zona_pantalla); + copyBackground(165, 140, 229, 117, 43, 59, drawSurface3, screenSurface); if (flags[12] == 1) - copyBackground(borracho_x[frame_borracho], 82, 170, 50, 40, 53, dir_dibujo3, dir_zona_pantalla); - diferencia = vez() - conta_ciego_vez; - if (diferencia > 6) { + copyBackground(_drunkX[actorFrames[kFrameDrunk]], 82, 170, 50, 40, 53, drawSurface3, screenSurface); + difference = getTime() - savedTime; + if (difference > 6) { if (flags[12] == 1) { - frame_borracho++; - if (frame_borracho == 8) { - frame_borracho = 0; + actorFrames[kFrameDrunk]++; + if (actorFrames[kFrameDrunk] == 8) { + actorFrames[kFrameDrunk] = 0; flags[12] = 0; } } else if ((_rnd->getRandomNumber(94) == 15) && (flags[13] == 0)) flags[12] = 1; - frame_velas++; - if (frame_velas == 3) - frame_velas = 0; - frame_piano++; - if (frame_piano == 9) - frame_piano = 0; - parpadeo = _rnd->getRandomNumber(10); - conta_ciego_vez = vez(); + actorFrames[kFrameCandles]++; + if (actorFrames[kFrameCandles] == 3) + actorFrames[kFrameCandles] = 0; + actorFrames[kFramePianist]++; + if (actorFrames[kFramePianist] == 9) + actorFrames[kFramePianist] = 0; + blinking = _rnd->getRandomNumber(10); + savedTime = getTime(); } } -void DrasculaEngine::update_15() { - copyRect(1, 154, 83, 122, 131, 44, dir_dibujo3, dir_zona_pantalla); -} - void DrasculaEngine::update_16_pre() { + if (currentChapter != 2) { + debug(4, "update_16_pre: Special case, current chapter is not 2, not performing update"); + return; + } + if (flags[17] == 0) - copyBackground(1, 103, 24, 72, 33, 95, dir_dibujo3, dir_zona_pantalla); + copyBackground(1, 103, 24, 72, 33, 95, drawSurface3, screenSurface); if (flags[19] == 1) - copyBackground(37, 151, 224, 115, 56, 47, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_17_pre() { - if (flags[15] == 1) - copyBackground(1, 135, 108, 65, 44, 63, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_17() { - copyRect(48, 135, 78, 139, 80, 30, dir_dibujo3, dir_zona_pantalla); + copyBackground(37, 151, 224, 115, 56, 47, drawSurface3, screenSurface); } void DrasculaEngine::update_18_pre() { - int diferencia; - int ronquido_x[] = {95, 136, 95, 136, 95, 95, 95, 95, 136, 95, 95, 95, 95, 95, 95, 95}; - int ronquido_y[] = {18, 18, 56, 56, 94, 94, 94, 94, 94, 18, 18, 18, 18, 18, 18, 18}; + int difference; + int snore_x[] = {95, 136, 95, 136, 95, 95, 95, 95, 136, 95, 95, 95, 95, 95, 95, 95}; + int snore_y[] = {18, 18, 56, 56, 94, 94, 94, 94, 94, 18, 18, 18, 18, 18, 18, 18}; if (flags[21] == 0) { - copyBackground(1, 69, 120, 58, 56, 61, dir_dibujo3, dir_zona_pantalla); - copyBackground(ronquido_x[frame_ronquido], ronquido_y[frame_ronquido], 124, 59, 40, 37, dir_dibujo3, dir_zona_pantalla); + copyBackground(1, 69, 120, 58, 56, 61, drawSurface3, screenSurface); + copyBackground(snore_x[actorFrames[kFrameSnore]], + snore_y[actorFrames[kFrameSnore]], + 124, 59, 40, 37, drawSurface3, screenSurface); } else - pon_vb(); - - diferencia = vez() - conta_ciego_vez; - if (diferencia > 9) { - frame_ronquido++; - if (frame_ronquido == 16) - frame_ronquido = 0; - conta_ciego_vez = vez(); + moveVonBraun(); + + difference = getTime() - savedTime; + if (difference > 9) { + actorFrames[kFrameSnore]++; + if (actorFrames[kFrameSnore] == 16) + actorFrames[kFrameSnore] = 0; + savedTime = getTime(); } } -void DrasculaEngine::update_18() { - if (flags[24] == 1) - copyRect(177, 1, 69, 29, 142, 130, dir_dibujo3, dir_zona_pantalla); - copyRect(105, 132, 109, 108, 196, 65, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_20() { - copyRect(1, 137, 106, 121, 213, 61, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_21_pre() { - if (flags[0] == 1) - copyBackground(2, 171, 84, 126, 17, 26, dir_dibujo3, dir_zona_pantalla); - - if (flags[10] == 1) - copyBackground(20, 163, 257, 149, 14, 34, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_22_pre() { - if (flags[24] == 1) - copyBackground(2, 187, 107, 106, 62, 12, dir_dibujo3, dir_zona_pantalla); - - if (flags[27] == 0) - copyBackground(32, 181, 203, 88, 13, 5, dir_dibujo3, dir_zona_pantalla); - - if (flags[26] == 0) - copyBackground(2, 133, 137, 83, 29, 53, dir_dibujo3, dir_zona_pantalla); - else - copyBackground(65, 174, 109, 145, 55, 25, dir_dibujo3, dir_zona_pantalla); -} - void DrasculaEngine::update_23_pre() { if (flags[11] == 1 && flags[0] == 0) - copyBackground(87, 171, 237, 110, 20, 28, dir_dibujo3, dir_zona_pantalla); + copyBackground(87, 171, 237, 110, 20, 28, drawSurface3, screenSurface); + // It might be possible to put these in an array, though I'm a bit unsure + // of the draw order if (flags[0] == 1) - copyBackground(29, 126, 239, 94, 57, 73, dir_dibujo3, dir_zona_pantalla); + copyBackground(29, 126, 239, 94, 57, 73, drawSurface3, screenSurface); if (flags[1] == 1) - copyRect(1, 135, 7, 94, 27, 64, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_24_pre() { - if (flags[1] == 1) - copyBackground(1, 163, 225, 124, 12, 36, dir_dibujo3, dir_zona_pantalla); - - if (flags[2] == 1) - copyBackground(14, 153, 30, 107, 23, 46, dir_dibujo3, dir_zona_pantalla); + copyRect(1, 135, 7, 94, 27, 64, drawSurface3, screenSurface); } void DrasculaEngine::update_26_pre() { - int diferencia; - - if (flags[2] == 1) - copyBackground(1, 130, 87, 44, 50, 69, dir_dibujo3, dir_zona_pantalla); + int difference; - if (flags[12] == 1) - copyBackground(52, 177, 272, 103, 27, 22, dir_dibujo3, dir_zona_pantalla); - - if (flags[18] == 0) - copyBackground(80, 133, 199, 95, 50, 66, dir_dibujo3, dir_zona_pantalla); - - if (parpadeo == 5 && flags[18] == 0) - copyBackground(52, 172, 226, 106, 3, 4, dir_dibujo3, dir_zona_pantalla); + if (blinking == 5 && flags[18] == 0) + copyBackground(52, 172, 226, 106, 3, 4, drawSurface3, screenSurface); - diferencia = vez() - conta_ciego_vez; - if (diferencia >= 10) { - parpadeo = _rnd->getRandomNumber(10); - conta_ciego_vez = vez(); + difference = getTime() - savedTime; + if (difference >= 10) { + blinking = _rnd->getRandomNumber(10); + savedTime = getTime(); } if (flags[20] == 1) - copyBackground(182, 133, 199, 95, 50, 66, dir_dibujo3, dir_zona_pantalla); + copyBackground(182, 133, 199, 95, 50, 66, drawSurface3, screenSurface); } void DrasculaEngine::update_26() { if (flags[29] == 1) - copyRect(93, 1, hare_x, hare_y, 45, 78, dir_hare_fondo, dir_zona_pantalla); - - copyRect(233, 107, 17, 102, 66, 92, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_27_pre() { - if (flags[5] == 1) - copyRect(1, 175, 59, 109, 17, 24, dir_dibujo3, dir_zona_pantalla); - - if (flags[6] == 1) - copyRect(19, 177, 161, 103, 18, 22, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_27() { - copyRect(38, 177, 103, 171, 21, 22, dir_dibujo3, dir_zona_pantalla); - copyRect(60, 162, 228, 156, 18, 37, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_29_pre() { - if (flags[4] == 1) - copyBackground(12, 113, 247, 49, 41, 84, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_29() { - copyRect(1, 180, 150, 126, 10, 17, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_30_pre() { - if (flags[4] == 1) - copyBackground(1, 148, 148, 66, 35, 51, dir_dibujo3, dir_zona_pantalla); - - if (flags[16] == 1) - copyBackground(37, 173, 109, 84, 20, 26, dir_dibujo3, dir_zona_pantalla); -} + copyRect(93, 1, curX, curY, 45, 78, backSurface, screenSurface); -void DrasculaEngine::update_31_pre() { - if (flags[13] == 1) - copyBackground(1, 163, 116, 41, 61, 36, dir_dibujo3, dir_zona_pantalla); - - if (flags[5] == 1) - copyBackground(1, 78, 245, 63, 30, 84, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_31() { - copyRect(63, 190, 223, 157, 17, 9, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_34_pre() { - if (flags[7] == 1) - copyBackground(99, 127, 73, 41, 79, 72, dir_dibujo3, dir_zona_pantalla); - - if (flags[8] == 1) - copyBackground(36, 129, 153, 41, 62, 65, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_34() { - copyRect(5, 171, 234, 126, 29, 23, dir_dibujo3, dir_zona_pantalla); + copyRect(233, 107, 17, 102, 66, 92, drawSurface3, screenSurface); } void DrasculaEngine::update_35_pre() { - if (flags[14] == 1) - copyBackground(1, 86, 246, 65, 68, 87, dir_dibujo3, dir_zona_pantalla); - if (flags[17] == 0 && flags[15] == 1) - copyBackground(111, 150, 118, 52, 40, 23, dir_dibujo3, dir_zona_pantalla); - - if (flags[17] == 1) - copyBackground(70, 150, 118, 52, 40, 23, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_35() { - copyRect(1, 174, 54, 152, 195, 25, dir_dibujo3, dir_zona_pantalla); -} - - -void DrasculaEngine::update_49_pre() { - if (flags[6] == 0) - copyBackground(2, 136, 176, 81, 49, 62, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_50() { - copyRect(4, 153, 118, 95, 67, 44, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_53_pre() { - if (flags[1] == 0) - copyRect(2, 113, 205, 50, 38, 86, dir_dibujo3, dir_zona_pantalla); - if (flags[2] == 0) - copyBackground(41, 159, 27, 117, 25, 40, dir_dibujo3, dir_zona_pantalla); - if (flags[9] == 1) - copyBackground(67, 184, 56, 93, 32, 15, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_54_pre() { - if (flags[5] == 1) - copyBackground(168, 156, 187, 111, 7, 11, dir_dibujo3, dir_zona_pantalla); - if (flags[12] == 1) - copyBackground(16, 156, 190, 64, 18, 24, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_56_pre() { - if (flags[10] == 0) - copyBackground(2, 126, 42, 67, 57, 67, dir_dibujo3, dir_zona_pantalla); - if (flags[11] == 1) - copyBackground(60, 160, 128, 97, 103, 38, dir_dibujo3, dir_zona_pantalla); -} - -void DrasculaEngine::update_57() { - copyRect(7, 113, 166, 61, 62, 82, dir_dibujo3, dir_zona_pantalla); + copyBackground(111, 150, 118, 52, 40, 23, drawSurface3, screenSurface); } void DrasculaEngine::update_58_pre() { - if (flags[0] == 0) - copyBackground(1, 156, 143, 120, 120, 43, dir_dibujo3, dir_zona_pantalla); - if (flags[1] == 2) - copyRect(252, 171, 173, 116, 25, 28, dir_dibujo3, dir_zona_pantalla); if (flags[1] == 0 && flags[0] == 0) - copyRect(278, 171, 173, 116, 25, 28, dir_dibujo3, dir_zona_pantalla); + copyRect(278, 171, 173, 116, 25, 28, drawSurface3, screenSurface); if (flags[2] == 0) { - pon_igor(); - pon_dr(); + placeIgor(); + placeDrascula(); } + // Not possible to put these in an array, as there are other surfaces + // copied above if (flags[3] == 1) - copyRect(1, 29, 204, 0, 18, 125, dir_dibujo3, dir_zona_pantalla); + copyRect(1, 29, 204, 0, 18, 125, drawSurface3, screenSurface); if (flags[8] == 1) - copyBackground(20, 60, 30, 64, 46, 95, dir_dibujo3, dir_zona_pantalla); + copyBackground(20, 60, 30, 64, 46, 95, drawSurface3, screenSurface); } void DrasculaEngine::update_58() { if (hare_se_ve == 1) - copyRect(67, 139, 140, 147, 12, 16, dir_dibujo3, dir_zona_pantalla); + copyRect(67, 139, 140, 147, 12, 16, drawSurface3, screenSurface); } void DrasculaEngine::update_59_pre() { - if (flags[4] == 0) - copyRect(1, 146, 65, 106, 83, 40, dir_dibujo3, dir_zona_pantalla); if (flags[9] == 1) { - copyBackground(65, 103, 65, 103, 49, 38, dir_dibujo1, dir_zona_pantalla); - copyRect(1, 105, 65, 103, 49, 38, dir_dibujo3, dir_zona_pantalla); + copyBackground(65, 103, 65, 103, 49, 38, bgSurface, screenSurface); + copyRect(1, 105, 65, 103, 49, 38, drawSurface3, screenSurface); } } void DrasculaEngine::update_60_pre() { - int velas_y[] = {158, 172, 186}; - int diferencia; + int difference; if (flags[5] == 0) - pon_dr(); + placeDrascula(); - copyBackground(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla); + copyBackground(123, _candleY[actorFrames[kFrameCandles]], 142, 14, 39, 13, drawSurface3, screenSurface); if (flag_tv == 1) - copyBackground(114, 158, 8, 30, 8, 23, dir_dibujo3, dir_zona_pantalla); + copyBackground(114, 158, 8, 30, 8, 23, drawSurface3, screenSurface); - diferencia = vez() - conta_ciego_vez; - parpadeo = _rnd->getRandomNumber(7); - if (parpadeo == 5 && flag_tv == 0) + difference = getTime() - savedTime; + blinking = _rnd->getRandomNumber(7); + if (blinking == 5 && flag_tv == 0) flag_tv = 1; - else if (parpadeo == 5 && flag_tv == 1) + else if (blinking == 5 && flag_tv == 1) flag_tv = 0; - if (diferencia > 6) { - frame_velas++; - if (frame_velas == 3) - frame_velas = 0; - conta_ciego_vez = vez(); + if (difference > 6) { + actorFrames[kFrameCandles]++; + if (actorFrames[kFrameCandles] == 3) + actorFrames[kFrameCandles] = 0; + savedTime = getTime(); } } void DrasculaEngine::update_60() { - if (hare_y - 10 < y_dr && flags[5] == 0) - pon_dr(); -} - -void DrasculaEngine::update_61() { - copyRect(1, 154, 83, 122, 131, 44, dir_dibujo3, dir_zona_pantalla); + if (curY - 10 < drasculaY && flags[5] == 0) + placeDrascula(); } void DrasculaEngine::update_62_pre() { - int velas_y[] = { 158, 172, 186 }; - int cirio_x[] = { 14, 19, 24 }; - int pianista_x[] = {1, 91, 61, 31, 91, 31, 1, 61, 31 }; - int borracho_x[] = {1, 42, 83, 124, 165, 206, 247, 1 }; - int diferencia; + int difference; - copyBackground(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla); - copyBackground(cirio_x[frame_velas], 146, 311, 80, 4, 8, dir_dibujo3, dir_zona_pantalla); + copyBackground(123, _candleY[actorFrames[kFrameCandles]], 142, 14, 39, 13, drawSurface3, screenSurface); + copyBackground(_candleX[actorFrames[kFrameCandles]], 146, 311, 80, 4, 8, drawSurface3, screenSurface); - if (parpadeo == 5) - copyBackground(1, 149, 127, 52, 9, 5, dir_dibujo3, dir_zona_pantalla); + if (blinking == 5) + copyBackground(1, 149, 127, 52, 9, 5, drawSurface3, screenSurface); - if (hare_x > 101 && hare_x < 155) - copyBackground(31, 138, 178, 51, 18, 16, dir_dibujo3, dir_zona_pantalla); + if (curX > 101 && curX < 155) + copyBackground(31, 138, 178, 51, 18, 16, drawSurface3, screenSurface); if (flags[11] == 0) - copyBackground(pianista_x[frame_piano], 157, 245, 130, 29, 42, dir_dibujo3, dir_zona_pantalla); + copyBackground(_pianistX[actorFrames[kFramePianist]], 157, 245, 130, 29, 42, drawSurface3, screenSurface); else if (flags[5] == 0) - copyBackground(145, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla); + copyBackground(145, 139, 228, 112, 47, 60, extraSurface, screenSurface); else - copyBackground(165, 140, 229, 117, 43, 59, dir_dibujo3, dir_zona_pantalla); + copyBackground(165, 140, 229, 117, 43, 59, drawSurface3, screenSurface); if (flags[12] == 1) - copyBackground(borracho_x[frame_borracho], 82, 170, 50, 40, 53, dir_dibujo3, dir_zona_pantalla); + copyBackground(_drunkX[actorFrames[kFrameDrunk]], 82, 170, 50, 40, 53, drawSurface3, screenSurface); - diferencia = vez() - conta_ciego_vez; - if (diferencia > 6) { + difference = getTime() - savedTime; + if (difference > 6) { if (flags[12] == 1) { - frame_borracho++; - if (frame_borracho == 8) { - frame_borracho = 0; + actorFrames[kFrameDrunk]++; + if (actorFrames[kFrameDrunk] == 8) { + actorFrames[kFrameDrunk] = 0; flags[12] = 0; } } else if ((_rnd->getRandomNumber(94) == 15) && (flags[13] == 0)) flags[12] = 1; - frame_velas++; - if (frame_velas == 3) - frame_velas = 0; - frame_piano++; - if (frame_piano == 9) - frame_piano = 0; - parpadeo = _rnd->getRandomNumber(10); - conta_ciego_vez = vez(); + actorFrames[kFrameCandles]++; + if (actorFrames[kFrameCandles] == 3) + actorFrames[kFrameCandles] = 0; + actorFrames[kFramePianist]++; + if (actorFrames[kFramePianist] == 9) + actorFrames[kFramePianist] = 0; + blinking = _rnd->getRandomNumber(10); + savedTime = getTime(); } } void DrasculaEngine::update_62() { - int borracho_x[] = { 1, 42, 83, 124, 165, 206, 247, 1 }; - - copyRect(1, 1, 0, 0, 62, 142, dir_dibujo2, dir_zona_pantalla); + copyRect(1, 1, 0, 0, 62, 142, drawSurface2, screenSurface); - if (hare_y + alto_hare < 89) { - copyRect(205, 1, 180, 9, 82, 80, dir_dibujo3, dir_zona_pantalla); - copyBackground(borracho_x[frame_borracho], 82, 170, 50, 40, 53, dir_dibujo3, dir_zona_pantalla); + if (curY + curHeight < 89) { + copyRect(205, 1, 180, 9, 82, 80, drawSurface3, screenSurface); + copyBackground(_drunkX[actorFrames[kFrameDrunk]], 82, 170, 50, 40, 53, drawSurface3, screenSurface); } } -void DrasculaEngine::update_63() { - copyRect(1, 154, 83, 122, 131, 44, dir_dibujo3, dir_zona_pantalla); -} +void DrasculaEngine::update_102() { + int pendulum_x[] = {40, 96, 152, 208, 264, 40, 96, 152, 208, 208, 152, 264, 40, 96, 152, 208, 264}; + int difference; + byte *pendulumSurface = drawSurface3; -void DrasculaEngine::update_pendulo() { - int pendulo_x[] = {40, 96, 152, 208, 264, 40, 96, 152, 208, 208, 152, 264, 40, 96, 152, 208, 264}; - int diferencia; - - if (frame_pen <= 4) - dir_pendulo = dir_dibujo3; - else if (frame_pen <= 11) - dir_pendulo = dir_hare_dch; + if (actorFrames[kFramePendulum] <= 4) + pendulumSurface = drawSurface3; + else if (actorFrames[kFramePendulum] <= 11) + pendulumSurface = extraSurface; else - dir_pendulo = dir_hare_frente; + pendulumSurface = frontSurface; - copyBackground(pendulo_x[frame_pen], 19, 152, 0, 55, 125, dir_pendulo, dir_zona_pantalla); + copyBackground(pendulum_x[actorFrames[kFramePendulum]], 19, 152, 0, 55, 125, pendulumSurface, screenSurface); if (flags[1] == 2) - copyRect(18, 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla); + copyRect(18, 145, 145, 105, 25, 29, drawSurface3, screenSurface); if (flags[1] == 0) - copyRect(44, 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla); - - diferencia = vez() - conta_ciego_vez; - if (diferencia > 8) { - frame_pen++; - if (frame_pen == 17) - frame_pen = 0; - conta_ciego_vez = vez(); + copyRect(44, 145, 145, 105, 25, 29, drawSurface3, screenSurface); + + difference = getTime() - savedTime; + if (difference > 8) { + actorFrames[kFramePendulum]++; + if (actorFrames[kFramePendulum] == 17) + actorFrames[kFramePendulum] = 0; + savedTime = getTime(); + } +} + +bool DrasculaEngine::checkAction(int fl) { + characterMoved = 0; + updateRoom(); + updateScreen(); + + hasAnswer = 1; + + if (menuScreen == 1 && roomParse(200, fl)) { + ; + } else if (menuScreen != 1 && roomParse(201, fl)) { + ; + } else if (menuScreen == 1) { + if (currentChapter == 1) { + hasAnswer = 0; + } else if (currentChapter == 2) { + if ((pickedObject == kVerbLook && fl == 22 && flags[23] == 0) + || (pickedObject == kVerbOpen && fl == 22 && flags[23] == 0)) { + talk(164); + flags[23] = 1; + withoutVerb(); + addObject(kItemMoney); + addObject(kItemTwoCoins); + } else if (pickedObject == kVerbLook && fl == 22 && flags[23] == 1) + talk(307); + else + hasAnswer = 0; + } else if (currentChapter == 3) { + hasAnswer = 0; + } else if (currentChapter == 4) { + if ((pickedObject == 18 && fl == 19) || (pickedObject == 19 && fl == 18)) { + withoutVerb(); + chooseObject(21); + removeObject(18); + removeObject(19); + } else if (pickedObject == kVerbLook && fl == 9) { + talk(482); + talk(483); + } else if (pickedObject == kVerbLook && fl == 19) { + talk(494); + talk(495); + } else + hasAnswer = 0; + } else if (currentChapter == 5) { + if (pickedObject == kVerbLook && fl == 9) { + talk(482); + talk(483); + } else + hasAnswer = 0; + } else if (currentChapter == 6) { + if (pickedObject == kVerbLook && fl == 9) { + talk(482); + talk(483); + } else + hasAnswer = 0; + } + } else { + if (currentChapter == 1) { + hasAnswer = 0; + } else if (currentChapter == 2) { + // Note: the original check was strcmp(num_room, "18.alg") + if (pickedObject == 11 && fl == 50 && flags[22] == 0 && roomNumber != 18) + talk(315); + else + hasAnswer = 0; + } else if (currentChapter == 3) { + if (roomNumber == 13) { + if (room(13, fl)) + return true; + } else + hasAnswer = 0; + } else if (currentChapter == 4) { + if (roomNumber == 28) + talk(178); + else if (pickedObject == 8 && fl == 50 && flags[18] == 0) + talk(481); + else if (pickedObject == 12 && fl == 50 && flags[18] == 0) + talk(487); + else if (roomNumber == 21) { + if (room(21, fl)) + return true; + } else + hasAnswer = 0; + } else if (currentChapter == 5) { + if (roomNumber == 56) { + if (room(56, fl)) + return true; + } else + hasAnswer = 0; + } else if (currentChapter == 6) { + if (pickedObject == kVerbLook && fl == 50 && flags[0] == 1) + talk(308); + else if (pickedObject == kVerbLook && fl == 50 && flags[0] == 0) + talk(310); + else if (roomNumber == 102) + room(102, fl); + else if (roomNumber == 60) { + if (room(60, fl)) + return true; + } + else + hasAnswer = 0; + } + } + + if (hasAnswer == 0) { + hasAnswer = 1; + + room(roomNumber, fl); + } + + if (hasAnswer == 0 && (hasName == 1 || menuScreen == 1)) + room(0, -1); + + return false; +} + +bool DrasculaEngine::room(int rN, int fl) { + if (!roomParse(rN, fl)) { + // Call room-specific parser + char rm[20]; + sprintf(rm, "room_%d", rN); + for (uint i = 0; i < _roomParsers.size(); i++) { + if (!strcmp(rm, _roomParsers[i]->desc)) { + debug(4, "Calling room parser %d", rN); + + return (this->*(_roomParsers[i]->proc))(fl); + } + } + + // We did not find any parser, let default one work + hasAnswer = 0; + } + + return false; +} + +void DrasculaEngine::enterRoom(int roomIndex) { + debug(2, "Entering room %d", roomIndex); + + char fileName[20]; + sprintf(fileName, "%d.ald", roomIndex); + int soc, l, martin = 0, objIsExit = 0; + float chiquez = 0, pequegnez = 0; + char pant1[20], pant2[20], pant3[20], pant4[20]; + char buffer[256]; + int palLevel = 0; + + hasName = 0; + + strcpy(currentData, fileName); + + _arj.open(fileName); + if (!_arj.isOpen()) { + error("missing data file %s", fileName); + } + int size = _arj.size(); + + getIntFromLine(buffer, size, &roomNumber); + getIntFromLine(buffer, size, &roomMusic); + getStringFromLine(buffer, size, roomDisk); + getIntFromLine(buffer, size, &palLevel); + + if (currentChapter == 2) + getIntFromLine(buffer, size, &martin); + + if (currentChapter == 2 && martin != 0) { + curWidth = martin; + getIntFromLine(buffer, size, &curHeight); + getIntFromLine(buffer, size, &feetHeight); + getIntFromLine(buffer, size, &stepX); + getIntFromLine(buffer, size, &stepY); + + getStringFromLine(buffer, size, pant1); + getStringFromLine(buffer, size, pant2); + getStringFromLine(buffer, size, pant3); + getStringFromLine(buffer, size, pant4); + + strcpy(menuBackground, pant4); + } + + getIntFromLine(buffer, size, &numRoomObjs); + + for (l = 0; l < numRoomObjs; l++) { + getIntFromLine(buffer, size, &objectNum[l]); + getStringFromLine(buffer, size, objName[l]); + getIntFromLine(buffer, size, &x1[l]); + getIntFromLine(buffer, size, &y1[l]); + getIntFromLine(buffer, size, &x2[l]); + getIntFromLine(buffer, size, &y2[l]); + getIntFromLine(buffer, size, &roomObjX[l]); + getIntFromLine(buffer, size, &roomObjY[l]); + getIntFromLine(buffer, size, &trackObj[l]); + getIntFromLine(buffer, size, &visible[l]); + getIntFromLine(buffer, size, &isDoor[l]); + if (isDoor[l] != 0) { + getStringFromLine(buffer, size, _targetSurface[l]); + getIntFromLine(buffer, size, &_destX[l]); + getIntFromLine(buffer, size, &_destY[l]); + getIntFromLine(buffer, size, &trackCharacter_alkeva[l]); + getIntFromLine(buffer, size, &alapuertakeva[l]); + updateDoor(l); + } + } + + getIntFromLine(buffer, size, &floorX1); + getIntFromLine(buffer, size, &floorY1); + getIntFromLine(buffer, size, &floorX2); + getIntFromLine(buffer, size, &floorY2); + + if (currentChapter != 2) { + getIntFromLine(buffer, size, &far); + getIntFromLine(buffer, size, &near); + } + _arj.close(); + + if (currentChapter == 2 && martin != 0) { + loadPic(pant2, extraSurface); + loadPic(pant1, frontSurface); + loadPic(pant4, backSurface); + } + + if (currentChapter == 2) { + if (martin == 0) { + stepX = STEP_X; + stepY = STEP_Y; + curHeight = CHARACTER_HEIGHT; + curWidth = CHARACTER_WIDTH; + feetHeight = FEET_HEIGHT; + loadPic(97, extraSurface); + loadPic(96, frontSurface); + loadPic(99, backSurface); + + strcpy(menuBackground, "99.alg"); + } + } + + for (l = 0; l < numRoomObjs; l++) { + if (objectNum[l] == objExit) + objIsExit = l; + } + + if (currentChapter == 2) { + if (curX == -1) { + curX = _destX[objIsExit]; + curY = _destY[objIsExit] - curHeight; + } + characterMoved = 0; + } + + loadPic(roomDisk, drawSurface3); + loadPic(roomNumber, bgSurface, HALF_PAL); + + copyBackground(0, 171, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3); + + setDefaultPalette(); + if (palLevel != 0) + setPaletteBase(palLevel); + assignBrightPalette(); + setDefaultPalette(); + setPaletteBase(palLevel + 2); + assignDarkPalette(); + + setBrightPalette(); + changeColor = -1; + + if (currentChapter == 2) + color_abc(kColorLightGreen); + + if (currentChapter != 2) { + for (l = 0; l <= floorY1; l++) + factor_red[l] = far; + for (l = floorY1; l <= 201; l++) + factor_red[l] = near; + + chiquez = (float)(near - far) / (float)(floorY2 - floorY1); + for (l = floorY1; l <= floorY2; l++) { + factor_red[l] = (int)(far + pequegnez); + pequegnez = pequegnez + chiquez; + } + } + + if (roomNumber == 24) { + for (l = floorY1 - 1; l > 74; l--) { + factor_red[l] = (int)(far - pequegnez); + pequegnez = pequegnez + chiquez; + } + } + + if (currentChapter == 5 && roomNumber == 54) { + for (l = floorY1 - 1; l > 84; l--) { + factor_red[l] = (int)(far - pequegnez); + pequegnez = pequegnez + chiquez; + } + } + + if (currentChapter != 2) { + if (curX == -1) { + curX = _destX[objIsExit]; + curY = _destY[objIsExit]; + curHeight = (CHARACTER_HEIGHT * factor_red[curY]) / 100; + curWidth = (CHARACTER_WIDTH * factor_red[curY]) / 100; + curY = curY - curHeight; + } else { + curHeight = (CHARACTER_HEIGHT * factor_red[curY]) / 100; + curWidth = (CHARACTER_WIDTH * factor_red[curY]) / 100; + } + characterMoved = 0; + } + + if (currentChapter == 2) { + soc = 0; + for (l = 0; l < 6; l++) { + soc += curWidth; + _frameX[l] = soc; + } + } + + if (currentChapter == 5) + hare_se_ve = 1; + + updateVisible(); + + if (currentChapter == 1) + isDoor[7] = 0; + + if (currentChapter == 2) { + if (roomNumber == 14 && flags[39] == 1) + roomMusic = 16; + else if (roomNumber == 15 && flags[39] == 1) + roomMusic = 16; + if (roomNumber == 14 && flags[5] == 1) + roomMusic = 0; + else if (roomNumber == 15 && flags[5] == 1) + roomMusic = 0; + + if (previousMusic != roomMusic && roomMusic != 0) + playMusic(roomMusic); + if (roomMusic == 0) + stopMusic(); + } else { + if (previousMusic != roomMusic && roomMusic != 0) + playMusic(roomMusic); + } + + if (currentChapter == 2) { + if (roomNumber == 9 || roomNumber == 2 || roomNumber == 14 || roomNumber == 18) + savedTime = getTime(); + } + if (currentChapter == 4) { + if (roomNumber == 26) + savedTime = getTime(); + } + + if (currentChapter == 4 && roomNumber == 24 && flags[29] == 1) + animation_7_4(); + + if (currentChapter == 5) { + if (roomNumber == 45) + hare_se_ve = 0; + if (roomNumber == 49 && flags[7] == 0) + animation_4_5(); + } + + updateRoom(); +} + +void DrasculaEngine::clearRoom() { + memset(VGA, 0, 64000); + _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); + _system->updateScreen(); +} + +bool DrasculaEngine::exitRoom(int l) { + debug(2, "Exiting room from door %d", l); + + int roomNum = 0; + + if (currentChapter == 1) { + if (objectNum[l] == 105 && flags[0] == 0) + talk(442); + else { + updateDoor(l); + if (isDoor[l] != 0) { + gotoObject(roomObjX[l], roomObjY[l]); + trackProtagonist = trackObj[l]; + updateRoom(); + updateScreen(); + characterMoved = 0; + trackProtagonist = trackCharacter_alkeva[l]; + objExit = alapuertakeva[l]; + doBreak = 1; + previousMusic = roomMusic; + + if (objectNum[l] == 105) { + animation_2_1(); + return true; + } + clearRoom(); + sscanf(_targetSurface[l], "%d", &roomNum); + curX = -1; + enterRoom(roomNum); + } + } + } else if (currentChapter == 2) { + updateDoor(l); + if (isDoor[l] != 0) { + gotoObject(roomObjX[l], roomObjY[l]); + characterMoved = 0; + trackProtagonist = trackCharacter_alkeva[l]; + objExit = alapuertakeva[l]; + doBreak = 1; + previousMusic = roomMusic; + if (objectNum[l] == 136) + animation_2_2(); + if (objectNum[l] == 124) + animation_3_2(); + if (objectNum[l] == 173) { + animation_35_2(); + return true; + } if (objectNum[l] == 146 && flags[39] == 1) { + flags[5] = 1; + flags[11] = 1; + } + if (objectNum[l] == 176 && flags[29] == 1) { + flags[29] = 0; + removeObject(kItemEarWithEarPlug); + addObject(kItemEarplugs); + } + clearRoom(); + sscanf(_targetSurface[l], "%d", &roomNum); + curX =- 1; + enterRoom(roomNum); + } + } else if (currentChapter == 3) { + updateDoor(l); + if (isDoor[l] != 0 && visible[l] == 1) { + gotoObject(roomObjX[l], roomObjY[l]); + trackProtagonist = trackObj[l]; + updateRoom(); + updateScreen(); + characterMoved = 0; + trackProtagonist = trackCharacter_alkeva[l]; + objExit = alapuertakeva[l]; + doBreak = 1; + previousMusic = roomMusic; + clearRoom(); + sscanf(_targetSurface[l], "%d", &roomNum); + curX =- 1; + enterRoom(roomNum); + } + } else if (currentChapter == 4) { + updateDoor(l); + if (isDoor[l] != 0) { + gotoObject(roomObjX[l], roomObjY[l]); + trackProtagonist = trackObj[l]; + updateRoom(); + updateScreen(); + characterMoved = 0; + trackProtagonist = trackCharacter_alkeva[l]; + objExit = alapuertakeva[l]; + doBreak = 1; + previousMusic = roomMusic; + + if (objectNum[l] == 108) + gotoObject(171, 78); + clearRoom(); + sscanf(_targetSurface[l], "%d", &roomNum); + curX = -1; + enterRoom(roomNum); + } + } else if (currentChapter == 5) { + updateDoor(l); + if (isDoor[l] != 0 && visible[l] == 1) { + gotoObject(roomObjX[l], roomObjY[l]); + trackProtagonist = trackObj[l]; + updateRoom(); + updateScreen(); + characterMoved = 0; + trackProtagonist = trackCharacter_alkeva[l]; + objExit = alapuertakeva[l]; + doBreak = 1; + previousMusic = roomMusic; + hare_se_ve = 1; + clearRoom(); + sscanf(_targetSurface[l], "%d", &roomNum); + curX = -1; + enterRoom(roomNum); + } + } else if (currentChapter == 6) { + updateDoor(l); + if (isDoor[l] != 0) { + gotoObject(roomObjX[l], roomObjY[l]); + trackProtagonist = trackObj[l]; + updateRoom(); + updateScreen(); + characterMoved = 0; + trackProtagonist = trackCharacter_alkeva[l]; + objExit = alapuertakeva[l]; + doBreak = 1; + previousMusic = roomMusic; + clearRoom(); + sscanf(_targetSurface[l], "%d", &roomNum); + curX = -1; + enterRoom(roomNum); + + if (objExit == 105) + animation_19_6(); + } + } + + return false; +} + +void DrasculaEngine::updateRoom() { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateRefresh_pre(); + if (currentChapter == 3) { + if (flags[0] == 0) + moveCharacters(); + else + copyRect(113, 54, curX - 20, curY - 1, 77, 89, drawSurface3, screenSurface); + } else { + moveCharacters(); + } + updateRefresh(); +} + +void DrasculaEngine::updateDoor(int doorNum) { + if (currentChapter == 1 || currentChapter == 3 || currentChapter == 5 || currentChapter == 6) + return; + else if (currentChapter == 2) { + if (objectNum[doorNum] == 138) + isDoor[doorNum] = flags[0]; + else if (objectNum[doorNum] == 136) + isDoor[doorNum] = flags[8]; + else if (objectNum[doorNum] == 156) + isDoor[doorNum] = flags[16]; + else if (objectNum[doorNum] == 163) + isDoor[doorNum] = flags[17]; + else if (objectNum[doorNum] == 177) + isDoor[doorNum] = flags[15]; + else if (objectNum[doorNum] == 175) + isDoor[doorNum] = flags[40]; + else if (objectNum[doorNum] == 173) + isDoor[doorNum] = flags[36]; + } else if (currentChapter == 4) { + if (objectNum[doorNum] == 101 && flags[0] == 0) + isDoor[doorNum] = 0; + else if (objectNum[doorNum] == 101 && flags[0] == 1 && flags[28] == 1) + isDoor[doorNum] = 1; + else if (objectNum[doorNum] == 103) + isDoor[doorNum] = flags[0]; + else if (objectNum[doorNum] == 104) + isDoor[doorNum] = flags[1]; + else if (objectNum[doorNum] == 105) + isDoor[doorNum] = flags[1]; + else if (objectNum[doorNum] == 106) + isDoor[doorNum] = flags[2]; + else if (objectNum[doorNum] == 107) + isDoor[doorNum] = flags[2]; + else if (objectNum[doorNum] == 110) + isDoor[doorNum] = flags[6]; + else if (objectNum[doorNum] == 114) + isDoor[doorNum] = flags[4]; + else if (objectNum[doorNum] == 115) + isDoor[doorNum] = flags[4]; + else if (objectNum[doorNum] == 116 && flags[5] == 0) + isDoor[doorNum] = 0; + else if (objectNum[doorNum] == 116 && flags[5] == 1 && flags[23] == 1) + isDoor[doorNum] = 1; + else if (objectNum[doorNum] == 117) + isDoor[doorNum] = flags[5]; + else if (objectNum[doorNum] == 120) + isDoor[doorNum] = flags[8]; + else if (objectNum[doorNum] == 122) + isDoor[doorNum] = flags[7]; + } +} + +void DrasculaEngine::openDoor(int nflag, int doorNum) { + if (flags[nflag] == 0) { + if (currentChapter == 1 /*|| currentChapter == 4*/) { + if (nflag != 7) { + playSound(3); + flags[nflag] = 1; + } + } else { + playSound(3); + flags[nflag] = 1; + } + + if (doorNum != NO_DOOR) + updateDoor(doorNum); + updateRoom(); + updateScreen(); + finishSound(); + withoutVerb(); + } +} + +void DrasculaEngine::closeDoor(int nflag, int doorNum) { + if (flags[nflag] == 1) { + playSound(4); + flags[nflag] = 0; + if (doorNum != NO_DOOR) + updateDoor(doorNum); + updateRoom(); + updateScreen(); + finishSound(); + withoutVerb(); } } diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp new file mode 100644 index 0000000000..de82899462 --- /dev/null +++ b/engines/drascula/saveload.cpp @@ -0,0 +1,255 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +bool DrasculaEngine::saveLoadScreen() { + char names[10][23]; + char file[50]; + char fileEpa[50]; + int n, n2, num_sav = 0, y = 27; + Common::InSaveFile *sav; + + clearRoom(); + + snprintf(fileEpa, 50, "%s.epa", _targetName.c_str()); + if (!(sav = _saveFileMan->openForLoading(fileEpa))) { + Common::OutSaveFile *epa; + if (!(epa = _saveFileMan->openForSaving(fileEpa))) + error("Can't open %s file", fileEpa); + for (n = 0; n < NUM_SAVES; n++) + epa->writeString("*\n"); + epa->finalize(); + delete epa; + if (!(sav = _saveFileMan->openForLoading(fileEpa))) { + error("Can't open %s file", fileEpa); + } + } + for (n = 0; n < NUM_SAVES; n++) + sav->readLine(names[n], 23); + delete sav; + + loadPic("savescr.alg", bgSurface, HALF_PAL); + + color_abc(kColorLightGreen); + + select[0] = 0; + + for (;;) { + y = 27; + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + for (n = 0; n < NUM_SAVES; n++) { + print_abc(names[n], 116, y); + y = y + 9; + } + print_abc(select, 117, 15); + setCursorTable(); + updateScreen(); + y = 27; + + updateEvents(); + + if (leftMouseButton == 1) { + delay(50); + for (n = 0; n < NUM_SAVES; n++) { + if (mouseX > 115 && mouseY > y + (9 * n) && mouseX < 115 + 175 && mouseY < y + 10 + (9 * n)) { + strcpy(select, names[n]); + + if (strcmp(select, "*")) + selectionMade = 1; + else { + enterName(); + strcpy(names[n], select); + if (selectionMade == 1) { + snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); + saveGame(file); + Common::OutSaveFile *tsav; + if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { + error("Can't open %s file", fileEpa); + } + for (n = 0; n < NUM_SAVES; n++) { + tsav->writeString(names[n]); + tsav->writeString("\n"); + } + tsav->finalize(); + delete tsav; + } + } + + print_abc(select, 117, 15); + y = 27; + for (n2 = 0; n2 < NUM_SAVES; n2++) { + print_abc(names[n2], 116, y); + y = y + 9; + } + if (selectionMade == 1) { + snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); + } + num_sav = n; + } + } + + if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && selectionMade == 1) { + enterName(); + strcpy(names[num_sav], select); + print_abc(select, 117, 15); + y = 27; + for (n2 = 0; n2 < NUM_SAVES; n2++) { + print_abc(names[n2], 116, y); + y = y + 9; + } + + if (selectionMade == 1) { + snprintf(file, 50, "%s%02d", _targetName.c_str(), n + 1); + saveGame(file); + Common::OutSaveFile *tsav; + if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { + error("Can't open %s file", fileEpa); + } + for (n = 0; n < NUM_SAVES; n++) { + tsav->writeString(names[n]); + tsav->writeString("\n"); + } + tsav->finalize(); + delete tsav; + } + } + + if (mouseX > 125 && mouseY > 123 && mouseX < 199 && mouseY < 149 && selectionMade == 1) { + if (!loadGame(file)) + return false; + break; + } else if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149 && selectionMade == 1) { + saveGame(file); + Common::OutSaveFile *tsav; + if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { + error("Can't open %s file", fileEpa); + } + for (n = 0; n < NUM_SAVES; n++) { + tsav->writeString(names[n]); + tsav->writeString("\n"); + } + tsav->finalize(); + delete tsav; + } else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180) + break; + else if (selectionMade == 0) { + print_abc("Please select a slot", 117, 15); + } + updateScreen(); + delay(200); + } + y = 26; + + delay(5); + } + + clearRoom(); + loadPic(roomNumber, bgSurface, HALF_PAL); + selectionMade = 0; + + return true; +} + +bool DrasculaEngine::loadGame(const char *gameName) { + int l, savedChapter, roomNum = 0; + Common::InSaveFile *sav; + + previousMusic = roomMusic; + menuScreen = 0; + if (currentChapter != 1) + clearRoom(); + + if (!(sav = _saveFileMan->openForLoading(gameName))) { + error("missing savegame file"); + } + + savedChapter = sav->readSint32LE(); + if (savedChapter != currentChapter) { + strcpy(saveName, gameName); + currentChapter = savedChapter - 1; + hay_que_load = 1; + return false; + } + sav->read(currentData, 20); + curX = sav->readSint32LE(); + curY = sav->readSint32LE(); + trackProtagonist = sav->readSint32LE(); + + for (l = 1; l < 43; l++) { + inventoryObjects[l] = sav->readSint32LE(); + } + + for (l = 0; l < NUM_FLAGS; l++) { + flags[l] = sav->readSint32LE(); + } + + takeObject = sav->readSint32LE(); + pickedObject = sav->readSint32LE(); + hay_que_load = 0; + sscanf(currentData, "%d.ald", &roomNum); + enterRoom(roomNum); + withoutVerb(); + + return true; +} + +void DrasculaEngine::saveGame(char gameName[]) { + Common::OutSaveFile *out; + int l; + + if (!(out = _saveFileMan->openForSaving(gameName))) { + error("Unable to open the file"); + } + out->writeSint32LE(currentChapter); + out->write(currentData, 20); + out->writeSint32LE(curX); + out->writeSint32LE(curY); + out->writeSint32LE(trackProtagonist); + + for (l = 1; l < 43; l++) { + out->writeSint32LE(inventoryObjects[l]); + } + + for (l = 0; l < NUM_FLAGS; l++) { + out->writeSint32LE(flags[l]); + } + + out->writeSint32LE(takeObject); + out->writeSint32LE(pickedObject); + + out->finalize(); + if (out->ioFailed()) + warning("Can't write file '%s'. (Disk full?)", gameName); + + delete out; + + playSound(99); + finishSound(); +} + +} // End of namespace Drascula diff --git a/engines/drascula/sound.cpp b/engines/drascula/sound.cpp new file mode 100644 index 0000000000..840d6c7cb5 --- /dev/null +++ b/engines/drascula/sound.cpp @@ -0,0 +1,159 @@ +/* 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 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 "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::updateVolume(Audio::Mixer::SoundType soundType, int prevVolume) { + int vol = _mixer->getVolumeForSoundType(soundType) / 16; + if (mouseY < prevVolume && vol < 15) + vol++; + if (mouseY > prevVolume && vol > 0) + vol--; + _mixer->setVolumeForSoundType(soundType, vol * 16); +} + +void DrasculaEngine::volumeControls() { + int masterVolume, voiceVolume, musicVolume; + + copyRect(1, 56, 73, 63, 177, 97, tableSurface, screenSurface); + updateScreen(73, 63, 73, 63, 177, 97, screenSurface); + + masterVolume = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4); + voiceVolume = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4); + musicVolume = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4); + + for (;;) { + updateRoom(); + + copyRect(1, 56, 73, 63, 177, 97, tableSurface, screenSurface); + + copyBackground(183, 56, 82, masterVolume, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4), tableSurface, screenSurface); + copyBackground(183, 56, 138, voiceVolume, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4), tableSurface, screenSurface); + copyBackground(183, 56, 194, musicVolume, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4), tableSurface, screenSurface); + + setCursorTable(); + + updateScreen(); + + updateEvents(); + + if (rightMouseButton == 1) { + delay(100); + break; + } + if (leftMouseButton == 1) { + delay(100); + if (mouseX > 80 && mouseX < 121) { + updateVolume(Audio::Mixer::kPlainSoundType, mouseY); + masterVolume = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4); + } + + if (mouseX > 136 && mouseX < 178) { + updateVolume(Audio::Mixer::kSFXSoundType, mouseY); + voiceVolume = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4); + } + + if (mouseX > 192 && mouseX < 233) { + updateVolume(Audio::Mixer::kMusicSoundType, mouseY); + musicVolume = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4); + } + } + + } + + updateEvents(); +} + +void DrasculaEngine::playSound(int soundNum) { + char file[20]; + sprintf(file, "s%i.als", soundNum); + + playFile(file); +} + +void DrasculaEngine::finishSound() { + delay(1); + + while (soundIsActive()) + _system->delayMillis(10); +} + +void DrasculaEngine::playMusic(int p) { + AudioCD.stop(); + AudioCD.play(p - 1, 1, 0, 0); +} + +void DrasculaEngine::stopMusic() { + AudioCD.stop(); +} + +int DrasculaEngine::musicStatus() { + return AudioCD.isPlaying(); +} + +void DrasculaEngine::stopSound() { + _mixer->stopHandle(_soundHandle); +} + +void DrasculaEngine::MusicFadeout() { + int org_vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); + for (;;) { + int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); + vol -= 10; + if (vol < 0) + vol = 0; + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol); + if (vol == 0) + break; + updateEvents(); + _system->updateScreen(); + _system->delayMillis(50); + } + AudioCD.stop(); + _system->delayMillis(100); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, org_vol); +} + +void DrasculaEngine::playFile(const char *fname) { + if (_arj.open(fname)) { + int soundSize = _arj.size(); + byte *soundData = (byte *)malloc(soundSize); + _arj.seek(32); + _arj.read(soundData, soundSize); + _arj.close(); + + _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_soundHandle, soundData, soundSize - 64, + 11025, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); + } else + warning("playFile: Could not open %s", fname); +} + +bool DrasculaEngine::soundIsActive() { + return _mixer->isSoundHandleActive(_soundHandle); +} + +} // End of namespace Drascula diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 3dea8c21a1..4d3187a0fd 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -27,2027 +27,942 @@ namespace Drascula { -void DrasculaEngine::talk_igor_dch(const char *dicho, const char *filename) { - int tiempou; - long tiempol; +int x_talk_dch[6] = {1, 25, 49, 73, 97, 121}; +int x_talk_izq[6] = {145, 169, 193, 217, 241, 265}; - int x_talk[8] = { 56, 82, 108, 134, 160, 186, 212, 238 }; - int cara; +void DrasculaEngine::talkInit(const char *filename) { + _rnd->setSeed((unsigned int)_system->getMillis() / 2); - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(BLANCO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(7); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - pon_igor(); - pon_dr(); - copyBackground(x_igor + 17, y_igor, x_igor + 17, y_igor, 37, 24, dir_dibujo1, dir_zona_pantalla); - - copyRect(x_talk[cara], 148, x_igor + 17, y_igor, 25, 24, dir_hare_frente, dir_zona_pantalla); - - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, x_igor + 26, y_igor); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + playFile(filename); } -void DrasculaEngine::talk_dr_izq(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int x_talk[8] = { 1, 40, 79, 118, 157, 196, 235, 274 }; - int cara; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); +bool DrasculaEngine::isTalkFinished(int* length) { + byte key = getScan(); + if (key != 0) + stopSound(); + if (soundIsActive()) + return false; - color_abc(ROJO); + return true; +} - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); +// talker types: +// 0: talk_igor_dch +// 1: talk_igor_front +// 2: talk_igor_door +// 3: talk_igor_seated +// 4: talk_igor_wig +void DrasculaEngine::talk_igor(int index, int talkerType) { + char filename[20]; + sprintf(filename, "I%i.als", index); + const char *said = _texti[_lang][index]; + int x_talk0[8] = { 56, 82, 108, 134, 160, 186, 212, 238 }; + int x_talk1[8] = { 56, 86, 116, 146, 176, 206, 236, 266 }; + int x_talk3[4] = { 80, 102, 124, 146 }; + int x_talk4[4] = { 119, 158, 197, 236 }; + int face; + int length = strlen(said); + + color_abc(kColorWhite); + + talkInit(filename); + + do { + if (talkerType == kIgorDch || talkerType == kIgorFront) { + face = _rnd->getRandomNumber(7); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateRefresh_pre(); + } else if (talkerType == kIgorSeated || talkerType == kIgorWig) { + face = _rnd->getRandomNumber(3); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateRefresh_pre(); } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(7); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - pon_igor(); - pon_dr(); - if (num_ejec == 6) - pon_hare(); - - copyBackground(x_dr, y_dr, x_dr, y_dr, 38, 31, dir_dibujo1, dir_zona_pantalla); - if (num_ejec == 6) - copyRect(x_talk[cara], 90, x_dr, y_dr, 38, 31, dir_dibujo2, dir_zona_pantalla); - else - copyRect(x_talk[cara], 90, x_dr, y_dr, 38, 31, dir_hare_fondo, dir_zona_pantalla); - - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, x_dr + 19, y_dr); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); + + if (talkerType == kIgorDch) { + placeIgor(); + placeDrascula(); + copyBackground(igorX + 17, igorY, igorX + 17, igorY, 37, 24, bgSurface, screenSurface); + copyRect(x_talk0[face], 148, igorX + 17, igorY, 25, 24, frontSurface, screenSurface); + updateRefresh(); + if (withVoices == 0) + centerText(said, igorX + 26, igorY); + updateScreen(); + pause(3); + } else if (talkerType == kIgorFront) { + if (currentChapter == 1 || currentChapter == 4) + placeIgor(); + if (currentChapter == 1) + placeDrascula(); + if (currentChapter == 1 || currentChapter == 6) + copyBackground(igorX, igorY, igorX, igorY, 29, 25, bgSurface, screenSurface); + copyRect(x_talk1[face], 173, igorX, igorY, 29, 25, frontSurface, screenSurface); + updateRefresh(); + if (withVoices == 0) + centerText(said, igorX + 26, igorY); + updateScreen(); + pause(3); + } else if (talkerType == kIgorDoor) { + updateRoom(); + if (withVoices == 0) + centerText(said, 87, 66); + updateScreen(); + } else if (talkerType == kIgorSeated || talkerType == kIgorWig) { + if (talkerType == kIgorSeated) + copyBackground(x_talk3[face], 109, 207, 92, 21, 23, drawSurface3, screenSurface); + else + copyBackground(x_talk4[face], 78, 199, 94, 38, 27, drawSurface3, screenSurface); + moveCharacters(); + updateRefresh(); + if (withVoices == 0) + centerText(said, 221, 102); + + updateScreen(); + pause(3); + } + } while (!isTalkFinished(&length)); - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; + if ((talkerType == kIgorFront && currentChapter == 6) || + talkerType == kIgorDoor || talkerType == kIgorSeated || talkerType == kIgorWig) { + updateRoom(); } - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (talkerType == kIgorDch || (talkerType == kIgorFront && currentChapter == 1)) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + placeIgor(); + placeDrascula(); + } + updateScreen(); } -void DrasculaEngine::talk_dr_dch(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +// Talker type 0: talk_dr_izq, 1: talk_dr_dch +void DrasculaEngine::talk_drascula(int index, int talkerType) { + const char *said = _textd[_lang][index]; + char filename[20]; + sprintf(filename, "d%i.als", index); int x_talk[8] = { 1, 40, 79, 118, 157, 196, 235, 274 }; - int cara; + int face; + int length = strlen(said); + int offset = (talkerType == 0) ? 0 : 7; + int offset2 = (talkerType == 0) ? 90 : 58; - int longitud; - longitud = strlen(dicho); + color_abc(kColorRed); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + talkInit(filename); - buffer_teclado(); + do { + face = _rnd->getRandomNumber(7); - color_abc(ROJO); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + updateRefresh_pre(); -bucless: + placeIgor(); + placeDrascula(); + if (currentChapter == 6) + moveCharacters(); - cara = _rnd->getRandomNumber(7); + copyBackground(drasculaX, drasculaY, drasculaX, drasculaY, 38 + offset, 31, bgSurface, screenSurface); + if (currentChapter == 6) + copyRect(x_talk[face], offset2, drasculaX + offset, drasculaY, 38, 31, drawSurface2, screenSurface); + else + copyRect(x_talk[face], offset2, drasculaX + offset, drasculaY, 38, 31, backSurface, screenSurface); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateRefresh_pre(); + updateRefresh(); - pon_igor(); - pon_dr(); - if (num_ejec == 6) - pon_hare(); + if (withVoices == 0) + centerText(said, drasculaX + 19, drasculaY); - copyBackground(x_dr, y_dr, x_dr, y_dr, 45, 31, dir_dibujo1, dir_zona_pantalla); - if (num_ejec != 6) - copyRect(x_talk[cara], 58, x_dr + 7, y_dr, 38, 31, dir_hare_fondo, dir_zona_pantalla); - else - copyRect(x_talk[cara], 58, x_dr + 7, y_dr, 38, 31, dir_dibujo2, dir_zona_pantalla); + updateScreen(); - updateRefresh(); + pause(3); - if (con_voces == 0) - centra_texto(dicho, x_dr + 19, y_dr); + } while (!isTalkFinished(&length)); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (talkerType == 0) + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - pause(3); + if (talkerType == 1 && currentChapter == 6) + updateRoom(); - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + placeIgor(); + placeDrascula(); - if (num_ejec == 6) - updateRoom(); + if (talkerType == 1 && currentChapter == 6) + moveCharacters(); - pon_igor(); - pon_dr(); - if (num_ejec == 6) - pon_hare(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::talk_solo(const char *dicho, const char *filename) { - int tiempou; - long tiempol; +void DrasculaEngine::talk_solo(const char *said, const char *filename) { + int length = strlen(said); - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - if (num_ejec == 1) + if (currentChapter == 1) color_abc(color_solo); - else if (num_ejec == 4) - color_abc(ROJO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); + else if (currentChapter == 4) + color_abc(kColorRed); + + talkInit(filename); + + if (currentChapter == 6) + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + + do { + if (withVoices == 0) { + if (currentChapter == 1) + centerText(said, 156, 90); + else if (currentChapter == 6) + centerText(said, 213, 72); + else if (currentChapter == 5) + centerText(said, 173, 92); } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + updateScreen(); + } while (!isTalkFinished(&length)); - if (num_ejec == 6) - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - -bucless: - - if (con_voces == 0) { - if (num_ejec == 1) - centra_texto(dicho, 156, 90); - else if (num_ejec == 6) - centra_texto(dicho, 213, 72); - else if (num_ejec == 5) - centra_texto(dicho, 173, 92); - } - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - if (num_ejec == 6) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (currentChapter == 6) { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); } } -void DrasculaEngine::talk_igor_frente(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int x_talk[8] = { 56, 86, 116, 146, 176, 206, 236, 266 }; - int cara; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(BLANCO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(7); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - if (num_ejec == 1 || num_ejec == 4) - pon_igor(); - if (num_ejec == 1) - pon_dr(); - if (num_ejec == 1 || num_ejec == 6) - copyBackground(x_igor, y_igor, x_igor, y_igor, 29, 25, dir_dibujo1, dir_zona_pantalla); - copyRect(x_talk[cara], 173, x_igor, y_igor, 29, 25, dir_hare_frente, dir_zona_pantalla); - - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, x_igor + 26, y_igor); +void DrasculaEngine::talk_bartender(int index, int talkerType) { + char filename[20]; + sprintf(filename, "t%i.als", index); + const char *said; - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - if (num_ejec == 6) { - updateRoom(); - } - - if (num_ejec == 1) { - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pon_igor(); - pon_dr(); + // Line 82 is a special case + if (index != 82) + said = _textt[_lang][index]; + else { + sprintf(filename, "d%i.als", index); + said = _textd[_lang][index]; } - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::talk_tabernero(const char *dicho, const char *filename) { - int tiempou; - long tiempol; int x_talk[9] = { 1, 23, 45, 67, 89, 111, 133, 155, 177 }; - int cara; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(MARRON); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); + int face; + int length = strlen(said); + + color_abc(kColorMaroon); + + talkInit(filename); + + do { + if (talkerType == 0) { + if (currentChapter == 1) { + if (musicStatus() == 0) + playMusic(roomMusic); + } else if (currentChapter == 2) { + if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0) + playMusic(roomMusic); + } + + face = _rnd->getRandomNumber(8); + } else { + face = _rnd->getRandomNumber(5); } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - if (num_ejec == 1) { - if (music_status() == 0) - playmusic(musica_room); - } else if (num_ejec == 2) { - if (music_status() == 0 && flags[11] == 0 && musica_room != 0) - playmusic(musica_room); - } - - cara = _rnd->getRandomNumber(8); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - updateRefresh_pre(); - - copyBackground(x_talk[cara], 2, 121, 44, 21, 24, dir_hare_dch, dir_zona_pantalla); - pon_hare(); - updateRefresh(); + updateRefresh_pre(); - if (con_voces == 0) - centra_texto(dicho, 132, 45); + if (talkerType == 0) + copyBackground(x_talk[face], 2, 121, 44, 21, 24, extraSurface, screenSurface); + else + copyBackground(x_talk[face], 130, 151, 43, 21, 24, drawSurface3, screenSurface); + moveCharacters(); + updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (withVoices == 0) + centerText(said, 132, 45); - pause(3); + updateScreen(); - byte key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete(sku); - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(3); + } while (!isTalkFinished(&length)); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::talk_bj(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_bj(int index) { + char filename[20]; + sprintf(filename, "BJ%i.als", index); + const char *said = _textbj[_lang][index]; int x_talk[5] = { 64, 92, 120, 148, 176 }; - int cara; + int face; + int length = strlen(said); - int longitud; - longitud = strlen(dicho); + color_abc(kColorWhite); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + talkInit(filename); - buffer_teclado(); + do { + if (currentChapter != 5) { + face = _rnd->getRandomNumber(4); - color_abc(BLANCO); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + updateRefresh_pre(); -bucless: - if (num_ejec != 5) { - cara = _rnd->getRandomNumber(4); + copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40, + bgSurface, screenSurface); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40, + drawSurface3, screenSurface); + moveCharacters(); + updateRefresh(); - updateRefresh_pre(); + if (withVoices == 0) + centerText(said, bjX + 7, bjY); - copyBackground(x_bj + 2, y_bj - 1, x_bj + 2, y_bj - 1, 27, 40, - dir_dibujo1, dir_zona_pantalla); + updateScreen(); - copyRect(x_talk[cara], 99, x_bj + 2, y_bj - 1, 27, 40, - dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); + pause(3); + } else { + updateRoom(); - if (con_voces == 0) - centra_texto(dicho, x_bj + 7, y_bj); + if (withVoices == 0) + centerText(said, 93, 80); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - } else { - updateRoom(); - - if (con_voces == 0) - centra_texto(dicho, 93, 80); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - } - - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + updateScreen(); + } + } while (!isTalkFinished(&length)); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::talk(const char *dicho, const char *filename) { - int tiempou; - long tiempol; +void DrasculaEngine::talk(int index) { + char name[20]; + sprintf(name, "%i.als", index); + talk(_text[_lang][index], name); +} - int suma_1_pixel = 0; - if (num_ejec != 2) - suma_1_pixel = 1; +void DrasculaEngine::talk(const char *said, const char *filename) { + int talkOffset = 0; + if (currentChapter != 2) + talkOffset = 1; int y_mask_talk = 170; - int x_talk_dch[6] = { 1, 25, 49, 73, 97, 121 }; - int x_talk_izq[6] = { 145, 169, 193, 217, 241, 265 }; - int cara; - - int longitud; - longitud = strlen(dicho); + int face; + int length = strlen(said); - if (num_ejec == 6) { - if (flags[0] == 0 && (!strcmp(num_room, "102.alg"))) { - talk_pen(dicho, filename); + if (currentChapter == 6) { + if (flags[0] == 0 && roomNumber == 102) { + talk_pen(said, filename, 0); return; } - if (flags[0] == 0 && (!strcmp(num_room, "58.alg"))) { - talk_pen2(dicho, filename); + if (flags[0] == 0 && roomNumber == 58) { + talk_pen(said, filename, 1); return; } } - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - if (num_ejec != 2) { - if (factor_red[hare_y + alto_hare] == 100) - suma_1_pixel = 0; + if (currentChapter != 2) { + if (factor_red[curY + curHeight] == 100) + talkOffset = 0; } - if (num_ejec == 2) - buffer_teclado(); - - if (num_ejec == 4) { - if (strcmp(num_room, "24.alg") || flags[29] == 0) { - color_abc(AMARILLO); + if (currentChapter == 4) { + if (roomNumber == 24 || flags[29] == 0) { + color_abc(kColorYellow); } } else { - color_abc(AMARILLO); - } - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); + color_abc(kColorYellow); } -bucless: - - cara = _rnd->getRandomNumber(5); + talkInit(filename); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + do { + face = _rnd->getRandomNumber(5); - updateRefresh_pre(); - if (num_ejec == 2) - copyBackground(hare_x, hare_y, ANCHOBJ + 1, 0, ancho_hare, alto_talk - 1, dir_zona_pantalla, dir_dibujo3); - else - copyBackground(hare_x, hare_y, ANCHOBJ + 1, 0, (int)(((float)ancho_hare / 100) * factor_red[hare_y + alto_hare]), - (int)(((float)(alto_talk - 1) / 100) * factor_red[hare_y + alto_hare]), - dir_zona_pantalla, dir_dibujo3); - - pon_hare(); - - if (num_ejec == 2) { - if (!strcmp(fondo_y_menu, "99.alg") || !strcmp(fondo_y_menu, "994.alg")) - copyBackground(ANCHOBJ + 1, 0, hare_x, hare_y, ancho_hare, alto_talk - 1, dir_dibujo3, dir_zona_pantalla); - } else { - copyBackground(ANCHOBJ + 1, 0, hare_x, hare_y, (int)(((float)ancho_hare / 100) * factor_red[hare_y + alto_hare]), - (int)(((float)(alto_talk - 1) / 100) * factor_red[hare_y + alto_hare]), - dir_dibujo3, dir_zona_pantalla); - } + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - if (sentido_hare == 0) { - if (num_ejec == 2) - copyRect(x_talk_izq[cara], y_mask_talk, hare_x + 8, hare_y - 1, ancho_talk, alto_talk, - dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_izq[cara], y_mask_talk, hare_x + (int)((8.0f / 100) * factor_red[hare_y + alto_hare]), - hare_y, ancho_talk, alto_talk, factor_red[hare_y + alto_hare], - dir_hare_dch, dir_zona_pantalla); - - updateRefresh(); - } else if (sentido_hare == 1) { - if (num_ejec == 2) - copyRect(x_talk_dch[cara], y_mask_talk, hare_x + 12, hare_y, ancho_talk, alto_talk, - dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_dch[cara], y_mask_talk, hare_x + (int)((12.0f / 100) * factor_red[hare_y + alto_hare]), - hare_y, ancho_talk, alto_talk, factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - updateRefresh(); - } else if (sentido_hare == 2) { - if (num_ejec == 2) - copyRect(x_talk_izq[cara], y_mask_talk, hare_x + 12, hare_y, ancho_talk, alto_talk, - dir_hare_frente, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_izq[cara], y_mask_talk, - suma_1_pixel + hare_x + (int)((12.0f / 100) * factor_red[hare_y + alto_hare]), - hare_y, ancho_talk, alto_talk, factor_red[hare_y + alto_hare], - dir_hare_frente, dir_zona_pantalla); - updateRefresh(); - } else if (sentido_hare == 3) { - if (num_ejec == 2) - copyRect(x_talk_dch[cara], y_mask_talk, hare_x + 8, hare_y, ancho_talk, alto_talk, - dir_hare_frente, dir_zona_pantalla); + updateRefresh_pre(); + if (currentChapter == 2) + copyBackground(curX, curY, OBJWIDTH + 1, 0, curWidth, talkHeight - 1, screenSurface, drawSurface3); else - reduce_hare_chico(x_talk_dch[cara], y_mask_talk, - suma_1_pixel + hare_x + (int)((8.0f / 100) * factor_red[hare_y + alto_hare]), - hare_y, ancho_talk,alto_talk, factor_red[hare_y + alto_hare], - dir_hare_frente, dir_zona_pantalla); - updateRefresh(); - } + copyBackground(curX, curY, OBJWIDTH + 1, 0, (int)(((float)curWidth / 100) * factor_red[curY + curHeight]), + (int)(((float)(talkHeight - 1) / 100) * factor_red[curY + curHeight]), + screenSurface, drawSurface3); + + moveCharacters(); + + if (currentChapter == 2) { + if (!strcmp(menuBackground, "99.alg") || !strcmp(menuBackground, "994.alg")) + copyBackground(OBJWIDTH + 1, 0, curX, curY, curWidth, talkHeight - 1, drawSurface3, screenSurface); + } else { + copyBackground(OBJWIDTH + 1, 0, curX, curY, (int)(((float)curWidth / 100) * factor_red[curY + curHeight]), + (int)(((float)(talkHeight - 1) / 100) * factor_red[curY + curHeight]), + drawSurface3, screenSurface); + } - if (con_voces == 0) - centra_texto(dicho, hare_x, hare_y); + if (trackProtagonist == 0) { + if (currentChapter == 2) + copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, talkWidth, talkHeight, + extraSurface, screenSurface); + else + reduce_hare_chico(x_talk_izq[face], y_mask_talk, curX + (int)((8.0f / 100) * factor_red[curY + curHeight]), + curY, talkWidth, talkHeight, factor_red[curY + curHeight], + extraSurface, screenSurface); + + updateRefresh(); + } else if (trackProtagonist == 1) { + if (currentChapter == 2) + copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight, + extraSurface, screenSurface); + else + reduce_hare_chico(x_talk_dch[face], y_mask_talk, curX + (int)((12.0f / 100) * factor_red[curY + curHeight]), + curY, talkWidth, talkHeight, factor_red[curY + curHeight], extraSurface, screenSurface); + updateRefresh(); + } else if (trackProtagonist == 2) { + if (currentChapter == 2) + copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight, + frontSurface, screenSurface); + else + reduce_hare_chico(x_talk_izq[face], y_mask_talk, + talkOffset + curX + (int)((12.0f / 100) * factor_red[curY + curHeight]), + curY, talkWidth, talkHeight, factor_red[curY + curHeight], + frontSurface, screenSurface); + updateRefresh(); + } else if (trackProtagonist == 3) { + if (currentChapter == 2) + copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, talkWidth, talkHeight, + frontSurface, screenSurface); + else + reduce_hare_chico(x_talk_dch[face], y_mask_talk, + talkOffset + curX + (int)((8.0f / 100) * factor_red[curY + curHeight]), + curY, talkWidth,talkHeight, factor_red[curY + curHeight], + frontSurface, screenSurface); + updateRefresh(); + } - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (withVoices == 0) + centerText(said, curX, curY); - pause(3); + updateScreen(); - byte key = getscan(); - if (num_ejec == 1 && key == Common::KEYCODE_ESCAPE) - term_int = 1; - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(3); + } while (!isTalkFinished(&length)); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - if (num_ejec == 1) { - if (music_status() == 0 && flags[11] == 0 && corta_musica == 0) - playmusic(musica_room); + if (currentChapter == 1) { + if (musicStatus() == 0 && flags[11] == 0 && musicStopped == 0) + playMusic(roomMusic); } } -void DrasculaEngine::talk_pianista(const char *dicho, const char *filename) { - int tiempou; - long tiempol; +void DrasculaEngine::talk_pianist(int index) { + char filename[20]; + sprintf(filename, "P%i.als", index); + const char* said = _textp[_lang][index]; int x_talk[4] = { 97, 145, 193, 241 }; - int cara; - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(BLANCO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: + int coords[7] = { 139, 228, 112, 47, 60, 221, 128 }; - cara = _rnd->getRandomNumber(3); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 139, 228, 112, 47, 60, - dir_hare_dch, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 221, 128); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - byte key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + color_abc(kColorWhite); + talk_generic(said, filename, x_talk, 4, coords, extraSurface); } -void DrasculaEngine::talk_borracho(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_drunk(int index) { + char filename[20]; + sprintf(filename, "B%i.als", index); + const char *said = _textb[_lang][index]; int x_talk[8] = { 1, 21, 41, 61, 81, 101, 121, 141 }; - int cara; - int longitud; - longitud = strlen(dicho); + int coords[7] = { 29, 177, 50, 19, 19, 181, 54 }; - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - if (num_ejec == 1) { - loadPic("an11y13.alg"); - decompressPic(dir_hare_frente, 1); - } + if (currentChapter == 1) + loadPic("an11y13.alg", frontSurface); flags[13] = 1; -bebiendo: - - if (flags[12] == 1) { + while (flags[12] == 1) { updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - goto bebiendo; - } - - buffer_teclado(); - - color_abc(VERDE_OSCURO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz\n"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); + updateScreen(); } -bucless: - - cara = _rnd->getRandomNumber(7); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 29, 177, 50, 19, 19, dir_hare_frente, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 181, 54); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + color_abc(kColorDarkGreen); - pause(3); - - byte key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + talk_generic(said, filename, x_talk, 8, coords, frontSurface); flags[13] = 0; - if (num_ejec == 1) { - loadPic("96.alg"); - decompressPic(dir_hare_frente, 1); - } + if (currentChapter == 1) + loadPic("96.alg", frontSurface); - if (num_ejec == 1) { - if (music_status() == 0 && flags[11] == 0) - playmusic(musica_room); - } else if (num_ejec == 2) { - if (music_status() == 0 && flags[11] == 0 && musica_room != 0) - playmusic(musica_room); + if (currentChapter == 1) { + if (musicStatus() == 0 && flags[11] == 0) + playMusic(roomMusic); + } else if (currentChapter == 2) { + if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0) + playMusic(roomMusic); } } -void DrasculaEngine::talk_vb(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_vonBraun(int index) { + char filename[20]; + sprintf(filename, "VB%i.als", index); + const char *said = _textvb[_lang][index]; int x_talk[6] = {1, 27, 53, 79, 105, 131}; - int cara; + int face; + int length = strlen(said); - int longitud; - longitud = strlen(dicho); + color_abc(kColorBrown); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + talkInit(filename); - buffer_teclado(); + copyBackground(vonBraunX + 5, 64, OBJWIDTH + 1, 0, 25, 27, bgSurface, drawSurface3); - color_abc(VON_BRAUN); + do { + if (trackVonBraun == 1) { + face = _rnd->getRandomNumber(5); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - - copyBackground(vb_x + 5, 64, ANCHOBJ + 1, 0, 25, 27, dir_dibujo1, dir_dibujo3); - -bucless: + moveCharacters(); + moveVonBraun(); - if (sentido_vb == 1) { - cara = _rnd->getRandomNumber(5); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - pon_hare(); - pon_vb(); - - copyBackground(ANCHOBJ + 1, 0, vb_x + 5, 64, 25, 27, dir_dibujo3, dir_zona_pantalla); - copyRect(x_talk[cara], 34, vb_x + 5, 64, 25, 27, dir_hare_frente, dir_zona_pantalla); - updateRefresh(); - } - - if (con_voces == 0) - centra_texto(dicho, vb_x, 66); + copyBackground(OBJWIDTH + 1, 0, vonBraunX + 5, 64, 25, 27, drawSurface3, screenSurface); + copyRect(x_talk[face], 34, vonBraunX + 5, 64, 25, 27, frontSurface, screenSurface); + updateRefresh(); + } - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (withVoices == 0) + centerText(said, vonBraunX, 66); - pause(3); + updateScreen(); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(3); + } while (!isTalkFinished(&length)); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if (music_status() == 0 && flags[11] == 0 && musica_room != 0) - playmusic(musica_room); + updateScreen(); + if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0) + playMusic(roomMusic); } -void DrasculaEngine::talk_vbpuerta(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int longitud; - longitud = strlen(dicho); +void DrasculaEngine::talk_vonBraunpuerta(int index) { + char filename[20]; + sprintf(filename, "VB%i.als", index); + const char *said = _textvb[_lang][index]; + int length = strlen(said); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + color_abc(kColorBrown); - buffer_teclado(); + talkInit(filename); - color_abc(VON_BRAUN); + do { + updateRoom(); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + if (withVoices == 0) + centerText(said, 150, 80); -bucless: + updateScreen(); + } while (!isTalkFinished(&length)); updateRoom(); - if (con_voces == 0) - centra_texto(dicho, 150, 80); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - if (music_status() == 0 && flags[11] == 0 && musica_room != 0) - playmusic(musica_room); + updateScreen(); + if (musicStatus() == 0 && flags[11] == 0 && roomMusic != 0) + playMusic(roomMusic); } -void DrasculaEngine::talk_ciego(const char *dicho, const char *filename, const char *sincronia) { - byte *num_cara; +void DrasculaEngine::talk_blind(int index) { + // Special case: a second array is used for sync here + // Also, the blind man's texts in the first array and his + // voice files start from 58, not 1 + char filename[20]; + sprintf(filename, "d%i.als", index + TEXTD_START - 1); + const char *said = _textd[_lang][index + TEXTD_START - 1]; + const char *syncChar = _textd1[_lang][index - 1]; + + byte *faceBuffer; int p = 0; - int pos_ciego[6]; - int cara = 0; + int pos_blind[6] = { 0, 2, 73, 1, 126, 149 }; + int length = strlen(said); - int longitud; - longitud = strlen(dicho); + color_abc(kColorBrown); - buffer_teclado(); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); - color_abc(VON_BRAUN); + talkInit(filename); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + do { + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + pos_blind[5] = 149; + char c = toupper(syncChar[p]); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); + if (c == '0' || c == '2' || c == '4' || c == '6') + pos_blind[0] = 1; + else + pos_blind[0] = 132; + + if (c == '0' || c == '1') + faceBuffer = drawSurface3; + else if (c == '2' || c == '3') + faceBuffer = extraSurface; + else if (c == '4' || c == '5') + faceBuffer = backSurface; + else { + faceBuffer = frontSurface; + pos_blind[5] = 146; } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - - pos_ciego[1] = 2; - pos_ciego[2] = 73; - pos_ciego[3] = 1; - pos_ciego[4] = 126; - pos_ciego[5] = 149; - -bucless: - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - pos_ciego[5] = 149; - char c = toupper(sincronia[p]); - if (c == '0') - cara = 0; - if (c == '1') - cara = 1; - if (c == '2') - cara = 2; - if (c == '3') - cara = 3; - if (c == '4') - cara = 4; - if (c == '5') - cara = 5; - if (c == '6') - cara = 6; - if (c == '7') - cara = 7; - - if (cara == 0 || cara == 2 || cara == 4 || cara == 6) - pos_ciego[0] = 1; - else - pos_ciego[0] = 132; - - if (cara == 0) - num_cara = dir_dibujo3; - else if (cara == 1) - num_cara = dir_dibujo3; - else if (cara == 2) - num_cara = dir_hare_dch; - else if (cara == 3) - num_cara = dir_hare_dch; - else if (cara == 4) - num_cara = dir_hare_fondo; - else if (cara == 5) - num_cara = dir_hare_fondo; - else { - num_cara = dir_hare_frente; - pos_ciego[5] = 146; - } - - copyRectClip( pos_ciego, num_cara, dir_zona_pantalla); - if (con_voces == 0) - centra_texto(dicho, 310, 71); + copyRectClip( pos_blind, faceBuffer, screenSurface); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - pause(2); - p++; + if (withVoices == 0) + centerText(said, 310, 71); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + updateScreen(); + pause(2); + p++; + } while (!isTalkFinished(&length)); } -void DrasculaEngine::talk_hacker(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); +void DrasculaEngine::talk_hacker(int index) { + char filename[20]; + sprintf(filename, "d%i.als", index); + const char *said = _textd[_lang][index]; + int length = strlen(said); - buffer_teclado(); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + color_abc(kColorYellow); - color_abc(AMARILLO); + talkInit(filename); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - if (con_voces == 0) - centra_texto(dicho, 156, 170); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - key = 0; + do { + if (withVoices == 0) + centerText(said, 156, 170); + updateScreen(); + } while (!isTalkFinished(&length)); } -void DrasculaEngine::talk_lobo(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_werewolf(int index) { + char filename[20]; + sprintf(filename, "L%i.als", index); + const char *said = _textl[_lang][index]; int x_talk[9] = {52, 79, 106, 133, 160, 187, 214, 241, 268}; - int cara; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - color_abc(ROJO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + int coords[7] = { 136, 198, 81, 26, 24, 203, 78 }; -bucless: - - cara = _rnd->getRandomNumber(8); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 136, 198, 81, 26, 24, dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 203, 78); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + color_abc(kColorRed); + talk_generic(said, filename, x_talk, 9, coords, drawSurface3); } -void DrasculaEngine::talk_mus(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_mus(int index) { + char filename[20]; + sprintf(filename, "E%i.als", index); + const char *said = _texte[_lang][index]; int x_talk[8] = { 16, 35, 54, 73, 92, 111, 130, 149}; - int cara; + int coords[7] = { 156, 190, 64, 18, 24, 197, 64 }; - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(BLANCO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(7); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 156, 190, 64, 18, 24, dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 197, 64); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + color_abc(kColorWhite); + talk_generic(said, filename, x_talk, 8, coords, drawSurface3); } -void DrasculaEngine::talk_pen(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_pen(const char *said, const char *filename, int talkerType) { int x_talk[8] = {112, 138, 164, 190, 216, 242, 268, 294}; - int cara; - - int longitud; - longitud = strlen(dicho); + int x_talk2[5] = {122, 148, 174, 200, 226}; + int face; + int length = strlen(said); flags[1] = 1; - updateRoom(); - copyRect(44, 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(AMARILLO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(7); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyRect(x_talk[cara], 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla); - - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 160, 105); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; + if (talkerType == 0) { + updateRoom(); + copyRect(44, 145, 145, 105, 25, 29, drawSurface3, screenSurface); + updateScreen(); } - flags[1] = 0; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateRefresh_pre(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::talk_pen2(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int x_talk[5]={122, 148, 174, 200, 226}; - int cara; + color_abc(kColorYellow); - int longitud; - longitud = strlen(dicho); + talkInit(filename); - flags[1] = 1; + do { + if (talkerType == 0) + face = _rnd->getRandomNumber(7); + else + face = _rnd->getRandomNumber(4); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateRefresh_pre(); - buffer_teclado(); + if (talkerType == 0) + copyRect(x_talk[face], 145, 145, 105, 25, 29, drawSurface3, screenSurface); + else + copyBackground(x_talk2[face], 171, 173, 116, 25, 28, drawSurface3, screenSurface); - color_abc(AMARILLO); + updateRefresh(); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); + if (withVoices == 0) { + if (talkerType == 0) + centerText(said, 160, 105); + else + centerText(said, 195, 107); } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(4); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - copyBackground(x_talk[cara], 171, 173, 116, 25, 28, dir_dibujo3, dir_zona_pantalla); + updateScreen(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 195, 107); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(3); + } while (!isTalkFinished(&length)); flags[1] = 0; - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); updateRefresh_pre(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::talk_taber2(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int x_talk[6] = {1, 23, 45, 67, 89, 111}; - int cara; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(MARRON); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(5); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 130, 151, 43, 21, 24, dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 132, 45); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::talk_bj_cama(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - +void DrasculaEngine::talk_bj_bed(int index) { + char filename[20]; + sprintf(filename, "BJ%i.als", index); + const char *said = _textbj[_lang][index]; int x_talk[5] = {51, 101, 151, 201, 251}; - int cara; - - int longitud; - longitud = strlen(dicho); + int face; + int length = strlen(said); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + color_abc(kColorWhite); - buffer_teclado(); + talkInit(filename); - color_abc(BLANCO); + do { + face = _rnd->getRandomNumber(4); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); -bucless: - - cara = _rnd->getRandomNumber(4); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); + updateRefresh_pre(); - copyBackground(65, 103, 65, 103, 49, 38, dir_dibujo1, dir_zona_pantalla); - copyRect(x_talk[cara], 105, 65, 103, 49, 38, dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); + copyBackground(65, 103, 65, 103, 49, 38, bgSurface, screenSurface); + copyRect(x_talk[face], 105, 65, 103, 49, 38, drawSurface3, screenSurface); + moveCharacters(); + updateRefresh(); - if (con_voces == 0) - centra_texto(dicho, 104, 102); + if (withVoices == 0) + centerText(said, 104, 102); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); - pause(3); + pause(3); + } while (!isTalkFinished(&length)); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::talk_htel(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - char *num_cara; - +void DrasculaEngine::talk_htel(int index) { + char filename[20]; + sprintf(filename, "%i.als", index); + const char *said = _text[_lang][index]; + char *faceBuffer; int x_talk[3] = {1, 94, 187}; - int cara, pantalla; + int face, curScreen; + int length = strlen(said); - int longitud; - longitud = strlen(dicho); + color_abc(kColorYellow); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + talkInit(filename); - buffer_teclado(); - - color_abc(AMARILLO); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + do { + face = _rnd->getRandomNumber(2); + curScreen = _rnd->getRandomNumber(2); -bucless: - - cara = _rnd->getRandomNumber(2); - pantalla = _rnd->getRandomNumber(2); - - if (cara == 0 && pantalla == 0) - num_cara = (char *)dir_dibujo3; - else if (pantalla == 1) - num_cara = (char *)dir_hare_frente; - else - num_cara = (char *)dir_hare_fondo; - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + if (face == 0 && curScreen == 0) + faceBuffer = (char *)drawSurface3; + else if (curScreen == 1) + faceBuffer = (char *)frontSurface; + else + faceBuffer = (char *)backSurface; - copyBackground(x_talk[cara], 1, 45, 24, 92, 108, (byte *)num_cara, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - if (con_voces == 0) - centra_texto(dicho, 90, 50); + copyBackground(x_talk[face], 1, 45, 24, 92, 108, (byte *)faceBuffer, screenSurface); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - pause(3); + if (withVoices == 0) + centerText(said, 90, 50); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + updateScreen(); + pause(3); + } while (!isTalkFinished(&length)); - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateScreen(); } -void DrasculaEngine::talk_sinc(const char *dicho, const char *filename, const char *sincronia) { - int suma_1_pixel = 1; +void DrasculaEngine::talk_sync(const char *said, const char *filename, const char *syncChar) { + int talkOffset = 1; int y_mask_talk = 170; - int x_talk_dch[6] = {1, 25, 49, 73, 97, 121}; - int x_talk_izq[6] = {145, 169, 193, 217, 241, 265}; - int p, cara = 0; - - int longitud; - longitud = strlen(dicho); + int p, face = 0; + int length = strlen(said); + char buf[2]; - buffer_teclado(); + color_abc(kColorYellow); - color_abc(AMARILLO); - - if (num_ejec == 1) { - if (factor_red[hare_y + alto_hare] == 100) - suma_1_pixel = 0; + if (currentChapter == 1) { + if (factor_red[curY + curHeight] == 100) + talkOffset = 0; } p = 0; - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } + talkInit(filename); -bucless: - - if (sincronia[p] == '0') - cara = 0; - if (sincronia[p] == '1') - cara = 1; - if (sincronia[p] == '2') - cara = 2; - if (sincronia[p] == '3') - cara = 3; - if (sincronia[p] == '4') - cara = 4; - if (sincronia[p] == '5') - cara = 5; - if (sincronia[p] == '6') - cara = 6; - if (sincronia[p] == '7') - cara = 7; - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); + do { + strncpy(buf, &syncChar[p], 1); + face = atoi(buf); - updateRefresh_pre(); - if (num_ejec == 2) - copyBackground(hare_x, hare_y, ANCHOBJ + 1, 0, ancho_hare, alto_talk - 1, dir_zona_pantalla, dir_dibujo3); - else - copyBackground(hare_x, hare_y, ANCHOBJ + 1, 0, (int)(((float)ancho_hare / 100) * factor_red[hare_y + alto_hare]), - (int)(((float)(alto_talk - 1) / 100) * factor_red[hare_y + alto_hare]), dir_zona_pantalla, dir_dibujo3); - pon_hare(); - if (num_ejec == 2) { - if (alto_hare != 56) - copyBackground(ANCHOBJ + 1, 0, hare_x, hare_y, ancho_hare, alto_talk - 1, dir_dibujo3, dir_zona_pantalla); - } else - copyBackground(ANCHOBJ + 1, 0, hare_x, hare_y, (int)(((float)ancho_hare / 100) * factor_red[hare_y + alto_hare]), - (int)(((float)(alto_talk - 1) / 100) * factor_red[hare_y + alto_hare]), dir_dibujo3, dir_zona_pantalla); - - if (sentido_hare == 0) { - if (num_ejec == 2) - copyRect(x_talk_izq[cara], y_mask_talk, hare_x + 8, hare_y - 1, ancho_talk, alto_talk, dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_izq[cara], y_mask_talk, (int)(hare_x + (8.0f / 100) * factor_red[hare_y + alto_hare]), - hare_y, ancho_talk, alto_talk, factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - updateRefresh(); - } else if (sentido_hare == 1) { - if (num_ejec == 2) - copyRect(x_talk_dch[cara], y_mask_talk, hare_x + 12, hare_y, ancho_talk, alto_talk, dir_hare_dch, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_dch[cara], y_mask_talk, (int)(hare_x + (12.0f / 100) * factor_red[hare_y + alto_hare]), - hare_y, ancho_talk, alto_talk, factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla); - updateRefresh(); - } else if (sentido_hare == 2) { - if (num_ejec == 2) - copyRect(x_talk_izq[cara], y_mask_talk, hare_x + 12, hare_y, ancho_talk, alto_talk, dir_hare_frente, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_izq[cara], y_mask_talk, - (int)(suma_1_pixel + hare_x + (12.0f / 100) * factor_red[hare_y + alto_hare]), hare_y, - ancho_talk, alto_talk, factor_red[hare_y + alto_hare], dir_hare_frente, dir_zona_pantalla); - updateRefresh(); - } else if (sentido_hare == 3) { - if (num_ejec == 2) - copyRect(x_talk_dch[cara], y_mask_talk, hare_x + 8, hare_y, ancho_talk, alto_talk, dir_hare_frente, dir_zona_pantalla); - else - reduce_hare_chico(x_talk_dch[cara], y_mask_talk, - (int)(suma_1_pixel + hare_x + (8.0f / 100) * factor_red[hare_y + alto_hare]), hare_y, - ancho_talk, alto_talk, factor_red[hare_y + alto_hare], dir_hare_frente, dir_zona_pantalla); - updateRefresh(); - } + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); - if (con_voces == 0) - centra_texto(dicho, hare_x, hare_y); + updateRefresh_pre(); + if (currentChapter == 2) + copyBackground(curX, curY, OBJWIDTH + 1, 0, curWidth, talkHeight - 1, screenSurface, drawSurface3); + else + copyBackground(curX, curY, OBJWIDTH + 1, 0, (int)(((float)curWidth / 100) * factor_red[curY + curHeight]), + (int)(((float)(talkHeight - 1) / 100) * factor_red[curY + curHeight]), screenSurface, drawSurface3); + moveCharacters(); + if (currentChapter == 2) { + if (curHeight != 56) + copyBackground(OBJWIDTH + 1, 0, curX, curY, curWidth, talkHeight - 1, drawSurface3, screenSurface); + } else + copyBackground(OBJWIDTH + 1, 0, curX, curY, (int)(((float)curWidth / 100) * factor_red[curY + curHeight]), + (int)(((float)(talkHeight - 1) / 100) * factor_red[curY + curHeight]), drawSurface3, screenSurface); + + if (trackProtagonist == 0) { + if (currentChapter == 2) + copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, talkWidth, talkHeight, extraSurface, screenSurface); + else + reduce_hare_chico(x_talk_izq[face], y_mask_talk, (int)(curX + (8.0f / 100) * factor_red[curY + curHeight]), + curY, talkWidth, talkHeight, factor_red[curY + curHeight], extraSurface, screenSurface); + updateRefresh(); + } else if (trackProtagonist == 1) { + if (currentChapter == 2) + copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight, extraSurface, screenSurface); + else + reduce_hare_chico(x_talk_dch[face], y_mask_talk, (int)(curX + (12.0f / 100) * factor_red[curY + curHeight]), + curY, talkWidth, talkHeight, factor_red[curY + curHeight], extraSurface, screenSurface); + updateRefresh(); + } else if (trackProtagonist == 2) { + if (currentChapter == 2) + copyRect(x_talk_izq[face], y_mask_talk, curX + 12, curY, talkWidth, talkHeight, frontSurface, screenSurface); + else + reduce_hare_chico(x_talk_izq[face], y_mask_talk, + (int)(talkOffset + curX + (12.0f / 100) * factor_red[curY + curHeight]), curY, + talkWidth, talkHeight, factor_red[curY + curHeight], frontSurface, screenSurface); + updateRefresh(); + } else if (trackProtagonist == 3) { + if (currentChapter == 2) + copyRect(x_talk_dch[face], y_mask_talk, curX + 8, curY, talkWidth, talkHeight, frontSurface, screenSurface); + else + reduce_hare_chico(x_talk_dch[face], y_mask_talk, + (int)(talkOffset + curX + (8.0f / 100) * factor_red[curY + curHeight]), curY, + talkWidth, talkHeight, factor_red[curY + curHeight], frontSurface, screenSurface); + updateRefresh(); + } - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (withVoices == 0) + centerText(said, curX, curY); - p++; - pause(3); + updateScreen(); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + p++; + pause(3); + } while (!isTalkFinished(&length)); - if (num_ejec == 1 && music_status() == 0 && flags[11] == 0) - playmusic(musica_room); - if (num_ejec == 2 && music_status() == 0 && flags[11] == 0 && musica_room != 0) - playmusic(musica_room); + if (currentChapter == 1 && musicStatus() == 0 && flags[11] == 0) + playMusic(roomMusic); + if (currentChapter == 2 && musicStatus() == 0 && flags[11] == 0 && roomMusic != 0) + playMusic(roomMusic); } -void DrasculaEngine::talk_baul(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - int cara = 0, cara_antes; - int longitud; - - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); +void DrasculaEngine::talk_baul(int index) { + char filename[20]; + sprintf(filename, "d%i.als", index); + const char *said = _text[_lang][index]; + int face = 0, cara_antes; + int length = strlen(said); cara_antes = flags[19]; - color_abc(MARRON); - - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: + color_abc(kColorMaroon); - if (cara == 1) - cara = 0; - else - cara = 1; + talkInit(filename); - flags[19] = cara; - updateRoom(); + do { + face = (face == 1) ? 0 : 1; - if (con_voces == 0) - centra_texto(dicho, 263, 69); + flags[19] = face; + updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (withVoices == 0) + centerText(said, 263, 69); - pause(4); + updateScreen(); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(4); + } while (!isTalkFinished(&length)); flags[19] = cara_antes; updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); -} - -void DrasculaEngine::talk_igorpuerta(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int longitud; - longitud = strlen(dicho); - - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); - - buffer_teclado(); - - color_abc(BLANCO); - - if (hay_sb == 1){ - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - updateRoom(); - if (con_voces == 0) - centra_texto(dicho, 87, 66); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } - - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } -void DrasculaEngine::talk_igor_sentado(const char *dicho, const char *filename) { - int tiempou; - long tiempol; +void DrasculaEngine::talk_dr_grande(int index) { + char filename[20]; + sprintf(filename, "D%i.als", index); + const char *said = _textd[_lang][index]; + int x_talk[4] = {47, 93, 139, 185}; + int face; + int l = 0; + int length = strlen(said); - int x_talk[4] = { 80, 102, 124, 146 }; - int cara; + color_abc(kColorRed); - int longitud; - longitud = strlen(dicho); + talkInit(filename); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + do { + face = _rnd->getRandomNumber(3); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + copyBackground(interf_x[l] + 24, interf_y[l], 0, 45, 39, 31, drawSurface2, screenSurface); + copyBackground(x_talk[face], 1, 171, 68, 45, 48, drawSurface2, screenSurface); + l++; + if (l == 7) + l = 0; - buffer_teclado(); + if (withVoices == 0) + centerText(said, 191, 69); - color_abc(BLANCO); + updateScreen(); - if (hay_sb == 1) { - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - cara = _rnd->getRandomNumber(3); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 109, 207, 92, 21, 23, dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 221, 102); - - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); - - pause(3); - - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1) { - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(3); - updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + byte key = getScan(); + if (key == Common::KEYCODE_ESCAPE) + term_int = 1; + } while (!isTalkFinished(&length)); } -void DrasculaEngine::talk_igor_peluca(const char *dicho, const char *filename) { - int tiempou; - long tiempol; - - int x_talk[4] = {119, 158, 197, 236}; - int cara = 0; - - int longitud; - longitud = strlen(dicho); +void DrasculaEngine::talk_generic(const char* said, const char* filename, int* faces, int faceCount, int* coords, byte* surface) { + int face; + int length = strlen(said); + talkInit(filename); - tiempol = _system->getMillis(); - tiempou = (unsigned int)tiempol / 2; - _rnd->setSeed(tiempou); + do { + face = _rnd->getRandomNumber(faceCount - 1); - buffer_teclado(); - - color_abc(BLANCO); - - if (hay_sb == 1){ - sku = new Common::File; - sku->open(filename); - if (!sku->isOpen()) { - error("no puedo abrir archivo de voz"); - } - ctvd_init(2); - ctvd_speaker(1); - ctvd_output(sku); - } - -bucless: - - _rnd->getRandomNumber(3); - - copyBackground(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla); - - updateRefresh_pre(); - - copyBackground(x_talk[cara], 78, 199, 94, 38, 27, dir_dibujo3, dir_zona_pantalla); - pon_hare(); - updateRefresh(); - - if (con_voces == 0) - centra_texto(dicho, 221, 102); + copyBackground(0, 0, 0, 0, 320, 200, bgSurface, screenSurface); + updateRefresh_pre(); + copyBackground(faces[face], coords[0], coords[1], coords[2], + coords[3], coords[4], surface, screenSurface); + moveCharacters(); + updateRefresh(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + if (withVoices == 0) + centerText(said, coords[5], coords[6]); - pause(3); + updateScreen(); - int key = getscan(); - if (key != 0) - ctvd_stop(); - buffer_teclado(); - if (hay_sb == 1){ - if (LookForFree() != 0) - goto bucless; - delete sku; - sku = NULL; - ctvd_terminate(); - } else { - longitud = longitud - 2; - if (longitud > 0) - goto bucless; - } + pause(3); + } while (!isTalkFinished(&length)); updateRoom(); - updateScreen(0, 0, 0, 0, 320, 200, dir_zona_pantalla); + updateScreen(); } } // End of namespace Drascula diff --git a/engines/drascula/texts.cpp b/engines/drascula/texts.cpp deleted file mode 100644 index d4cde5b5fa..0000000000 --- a/engines/drascula/texts.cpp +++ /dev/null @@ -1,4342 +0,0 @@ -/* 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 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 "drascula/drascula.h" - -namespace Drascula { - -const char *_text[][501] = { -{ - "", - "ITS THE SECOND BIGGEST DOOR I'VE SEEN IN MY LIFE", - "NOT REALLY", - "THE CHURCH IS ALL BOARDED UP, IT MUST HAVE BEEN ABANDONED SEVERAL YEARS AGO", - "I HAVEN'T OPENED IT", - "WHAT SHOULD I DO, SHOULD I PULL IT OFF?", - "HI THERE DOOR, I'M GOING TO MAKE YOU A DOOR-FRAME", - "IT'S TOO MUCH FOR ME", - "THERE'S A WINDOW STOPPING THE GAME FROM WORKING PROPERLY", - "I CAN'T", - "YES, THAT'S DONE", - "WHY?", - "HI WINDOW, ARE YOU DOING ANYTHING TONIGHT?", - "NOT WITHOUT PERMISSION FROM THE TOWN HALL", - "IF ONLY THIS WINDOW WASN'T BOARDED UP...", - "YOO-HOO WINDOW!", - "HI THERE", - "LIKE MICROCHOF'S", - "I CAN'T REACH", - "IT'S ALRIGHT WHERE IT IS", - "", - "ITS A COFFIN IN THE SHAPE OF A CROSS", - "NO THANKS", - "HI DEAD MAN. NO, DON'T GET UP FOR MY SAKE", - "YES, JUST LIKE IN POLTERGEIST", - "", - "", - "I'LL BE BACK IN FIFTEEN MINUTES", - "FORBIDDEN TO PUT UP POSTERS", - "IT'S UNCLE EVARISTO'S TOMB", - "ITS LOCKED", - "I'VE GOT ONE", - "YOO HOO, UNCLE EVERISTO!", - "THERE'S NO REPLY", - "IT'S NOT WELL PARKED", - "IT'S A DOOR", - "A DRAWER IN THE TABLE", - "A SUSPICIOUS WARDROBE", - "HI WARDROBE, HOW ARE YOU?", - "", - "", - "IT'S AN ANCIENT CANDELABRUM", - "IT MUST HAVE BEEN HERE EVER SINCE YULE BRINNER HAD HAIR ON HIS HEAD", - "NO, ITS A RELIC", - "ITS A NICE ALTARPIECE", - "", - "HA, HA, HA", - "", - "NO", - "", - "HA, HE, HI, HO, HU, GREAT!", - "", - "", - "", - "I CAN'T SEE ANYTHING IN PARTICULAR", - "IT'S FERNAN, THE PLANT", - "IT'S ONE OF THE FENCES SPIKES", - "HEY! THERE'S A PACKET OF MATCHES UNDER HERE", - "LOOK! A PACKET OF KLEENEX, AND ONE'S STILL UNUSED", - "THERE ISN'T ANYTHING ELSE IN THE BUCKET", - "IT'S A BLIND MAN WHO CAN'T SEE", - "", - "", - "", - "", - "THAT'S A GREAT DEAL OF MONEY", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "THERE IS NOTHING SPECIAL ABOUT IT", - "IT'S NOT UNUSUAL", - "HEY, WHAT'S UP MAN?", - "HI", - "NOTHING NEW?", - "HOW IS THE FAMILY?", - "THAT IS JUST LIKE YOU!", - "BUT HOW DO I GET THAT?", - "MY RELIGION DOES NOT ALLOW ME", - "IT'D BE BETTER NOT", - "YEAH, SURE MAN!", - "NO WAY", - "IMPOSSIBLE", - "THIS WILL NOT OPEN", - "I CAN'T DO IT BY MYSELF", - "I COULD DO IT, BUT I JUST FEEL A LITTLE LAZY", - "I DO NOT SEE THE REASON", - "IT'S A QUITE NICE BRAIN", - "AND SO BRAIN, WHAT ARE YOU UP TONIGHT?", - "NO, IT MUST BE KEPT SOMEWHERE AWAY FROM THE MUTANT ACTION OF THE ATMOSPHERE", - "HE IS VERY STIFF, JUST LIKE MY BOSS", - "A VERY SHARP STICK", - "YOU FAITHFUL SHARP-PAINTED STICK, NOBLE TRANSILVAAANIAN OAK TREE", - "DAMN, I HAVE TO CUT MY NAILS!", - "B.J. IS IN THERE... SHE IS A REALLY HOT CHICK!", - "IT IS FIRMLY LOCKED", - "\"SAVE AWAY LOCKS LTD.\"", - "IT IS THE TYPICAL SKELETON YOU FIND IN THE DUNGEONS OF ALL THE GAMES", - "IT IS COMMONLY USED TO COMMUNICATE ELECTRICITY TO THE MACHINES CONNECTED TO IT", - "IT IS ABSOLUTELY HAND MADE BECAUSE THE JAPANESE MAKE THEM POCKET SIZE", - "I HAVE ONLY SEEN IN MY LIFE ANOTHER THING AS UGLY AS THIS ONE", - "FORGET IT. I AM NOT GOING TO TELL HIM ANYTHING IN CASE HE GETS MAD", - "IT SEEMS QUITE RATIONAL", - "IT IS A PICTURE OF PLATO WRITING HIS LOST DIALOGUE", - "I AM NOT ONE OF THOSE WHO TALKS TO POSTERS", - "THAT'S A VERY CUTE DESK", - "IT IS A VAMPIRES HUNTER'S DIPLOMA OFFICIALLY APPROVED BY OXFORD UNIVERSITY", - "IT'S A DARK NIGHT WITH FULL MOON", - "IT SEEMS LIKE THESE SCREWS ARE NOT MUCH TWISTED", - "DON'T LOOK NOW, BUT I THINK THAT A HIDDEN CAMERA IS FOCUSING ON ME", - "THAT'S A VERY MODERN STICK DETECTOR", - "NO. THE LABORATORY IS ON THE SECOND FLOOR", - "A NICE BEDSIDE TABLE", - "IT'S A LOT OF MONEY THAT CAN'T BE MISSING IN ANY VALUABLE ADVENTURE", - "IF I WERE A RICH MAN, DUBIDUBIDUBIDUBIDUBIDUBIDUBIDU", - "THOSE ARE STRANGE LEAVES. THEY MUST HAVE BROUGHT THEM FROM SOUTH AMERICA OR AROUND THERE", - "I DON'T THINK THEY WOULD ANSWER ME", - "THAT'S A BEAUTIFUL WOODEN CRUCIFIX. THE ICON DOESN'T REALLY GET ALL THE BEAUTY WITHIN IT", - "I ONLY PRAY BEFORE I GO TO BED", - "HEY, THIS PIKE SEEMS A LITTLE BIT LOOSE!", - "I HOPE YOU WON'T COMPLAIN ABOUT GETTING NO CLUES FROM ME", - "IT'S A QUITE CONVENTIONAL PIKE", - "THEY ARE CUTE, THOUGH THEY ARE COVERED WITH A LITTLE BIT OF SHIT", - "NO, THEY WON'T HEAR ME. HA,HA,HA THIS IS GREAT!", - "\"SLEEPING BEAUTY\" FROM CHAIKOSKY, OR CHOIFRUSKY, OR WHATEVER IT IS", - "VERY TEMPTING", - "NO, I'M NOT ONE OF THOSE WHO PUT USED BUBBLE GUMS IN THEIR MOUTH", - "THAT'S A VERY NICE SICKLE. I WONDER WHERE THE HAMMER MAY BE", - "TOBACCO MANUFACTURERS WARN ABOUT HEALTH BEING SERIOUSLY DAMAGED BY SANITARY AUTHORITIES", - "AN ABSOLUTELY NORMAL CANDLE, INCLUDING WAX AND EVERYTHING", - "THESE TWO SHINY COINS DO REALLY GLITTER!", - "THIS SHINY COIN DOES REALLY GLITTER!", - "WITH THIS I WILL BE IMMUNE AGAINST VAMPIRE'S BITES", - "NO, IT'S IS NOT THE RIGHT MOMENT YET", - "THERE IS A ONE THOUSAND BILL AND A COUPLE COINS", - "IT SAYS \"PLEASE, DO NOT THROW FOOD TO THE PIANIST\"", - "OMELET, 200. FRIED FISH, 150, MAYONNAISE POTATOES, 225", - "BEST BURGERS ON THIS SIDE OF THE DANUBE, ONLY FOR 325!", - "THAT'S A NICE SKULL WITH A VERY PENETRATING LOOK, HA, HA, HA, HA, THAT WAS GOOD!", - "HI SKULL, YOU REMIND ME OF UNCLE HAMLET", - "I HAVE THE HABIT OF NOT TOUCHING THINGS THAT HAVE BEEN ALIVE", - "IT'S A BIN", - "IT'S A BET FOR TONIGHT'S GAME", - "I WONDER WHAT THERE IS BEHIND THAT", - "HEY, THAT CURTAIN IS NOT MOVING!", - "MAN, THIS CASTLE IS REALLY GLOOMY", - "I CAN'T, HE IS TOO FAR AWAY TO HEAR ME", - "IT'S THE TYPICAL TRANSILVANIAN FOREST, WITH TREES", - "MAN YOU REALLY SAY STUPID THINGS, AND THIS IS TOO DARK!", - "GARCIA, CANDY STORE. SWEETS AND BUBBLE GUM", - "A VERY NICE DOOR", - "IT'S CLOSED", - "A COMPLETELY LOCKED BARREL", - "", - "AREN'T THESE BUGS REALLY CUTE?", - "BSSST, PUSSYCAT... LITTLE CAT", - "THERE IS NO ANSWER", - "THE MOON IS A SATELLITE THAT TURNS AROUND THE EARTH WITH A REVOLUTION PERIOD OF 28 DAYS", - "HI, LOONY MOON", - "IT'S TOTALLY BLOCKED UP WITH PLANKS", - "IT'S IMPOSSIBLE. NOT EVEN THAT TOUGH GUY FROM TV COULD OPEN THIS", - "HEY! THE SHADOW OF THAT CYPRESS LOOKS PROLONGED TO ME!", - "YOU, BARTENDER...!!", - "I WOULD LIKE TO HAVE A ROOM PLEASE", - "DO YOU KNOW WHERE I CAN FIND THE SO CALLED DRASCULA?", - "YES, SO WHAT?", - "SO?", - "IS...THAT RIGHT?", - "GOOD QUESTION. NOW, LET ME TELL YOU MY STORY. LOOK...", - "IT'S JUST FIVE MINUTES", - "I'M JOHN HACKER AND I REPRESENT A BRITISH PROPERTY COMPANY", - "AS FAR AS I KNOW, COUNT DRASCULA WANTS TO BUY SOME PIECES OF LAND IN GIBRALTAR AND MY COMPANY SENT ME HERE TO NEGOTIATE THE SELLING", - "I THINK I'M GOING BACK TO MY MUM'S TOMORROW FIRST THING IN THE MORNING", - "BEAUTIFUL NIGHT, HUH?", - "NO, NOTHING", - "YOU...PIANIST...!!!!", - "BEAUTIFUL NIGHT", - "AND IT'S NOT EVEN COLD OR ANYTHING", - "ALL RIGHT, I'LL JUST LET YOU GO ON PLAYING", - "WELL THEN", - "HI BOSS, HOW ARE YOU?", - "AND HOW IS THE FAMILY?", - "THIS IS QUITE GROOVY, HUH?", - "I'D BETTER NOT SAY ANYTHING", - "THERE IS NO PLACE LIKE HOME. THERE IS NO...WHAT?, BUT YOU ARE NOT AUNT EMMA. AS A MATTER OF FACT, I DON'T HAVE ANY AUNT EMMA!", - "YES, SO DOES MINE. YOU CAN CALL ME ANYTHING YOU WANT, BUT IF YOU CALL ME JHONNY, I'LL COME TO YOU LIKE A DOG", - "AREN'T I JUST A FUNNY GUY, HUH?. BY THE WAY, WHERE AM I?", - "YES", - "SHOOT...!", - "OH, SURE...OF COURSE!", - "WELL, THANKS VERY MUCH FOR YOUR HELP. I WON'T BOTHER YOU ANYMORE IF YOU PLEASE TELL ME WHERE THE DOOR IS...", - "IT'S BECAUSE THE KNOCK MUST HAVE AFFECTED MY BRAIN...I CAN'T SEE A THING...", - "WELL...THAT DOESN'T MATTER. I ALWAYS CARRY AN SPARE ONE", - "WOW, WHAT A HOT CHICK!! I DIDN'T NOTICE!, BUT OF COURSE, I WASN'T WEARING MY GLASSES", - "HEY...", - "AND ALL THIIIISSS???", - "DON'T WORRY B.J. HONEY, I'LL SAVE YOU FROM FALLING INTO HIS CLUTCHES...", - "YOU REALLY GOT ME MAD MAN...", - "AHHH A WEREWOLF!! DIE YOU DAMNED EVIL!", - "YES, WELL...", - "YES, WELL...I THINK I'LL JUST GO ON MY WAY. EXCUSE ME", - "WHAT?", - "TO TELL YOU THE TRUTH...ON SECOND THOUGHTS...I DON'T REALLY THINK SO", - "AND SO TELL ME YOU ERUDITE PHILOSOPHER, IS THERE ANY RELATIONSHIP CAUSE-AND-EFFECT BETWEEN SILLY AND BILLY?", - "OK, OK, FORGET IT. I DON'T EVEN KNOW WHU I SAID ANYTHING ABOUT IT", - "WHAT ARE YOU DONIG HERE PHILOSPOZING INSTEAD OF BEING EATING SOME PEOPLE", - "HOW COME?", - "HEY, COULD YOU SAY AGAIN ALL THAT ABOUT PRE-EVOLUTIONARY RELATIONSHIPS?", - "YES, MAN. ALL THAT STUFF YOU TOLD ME ABOUT NEFORE. I DIDN'D GET IT VERY WELL, YOU KNOW", - "NO, I'D RATHER NOT SAY ANYTHING, IN CASE HE GETS ANGRY OR SOMETHING...", - "HELLO?", - "YES, WHAT'S UP?", - "WELL, NOW THAT YOU MENTION IT, I'LL TELL YOU THAT...", - "", - "WELL, THANKS FOR CALLING. BY THE WAY, THIS IS NOT THE CASE, OF COURSE, BUT WHAT COULD HAPPEN IF A VAMPIRE GOT THE RECIPE BY ANY CHANCE?", - "WELL ANYWAY. LISTEN, DOESN'T THIS LOOK TO YOU LIKE A LOT OF CRAP TO END UP SOON WITH THE GAME?. WELL, MAYBE NOT", - "IT'S EMPTY!", - "WHY DID YOU TAKE MY ONLY LOVE, B.J., AWAY FROM ME?. LIFE HAS NO MEANING FOR WITHOUT HER", - "HER BRAIN?\?!!", - "TO TELL YOU THE TRUTH, I THINK I HAD JUST ENOUGH WITH YOUR OF YOUR LITTLE MONSTER", - "OH PLEASE, HOLLY VIRGIN, DON'T LET ANYTHING WORSE HAPPEN TO ME!!", - "YOU ARE NOT GOING TO GET YOUR WAY. I'M SURE SUPERMAN WILL CAME AND RESCUE ME!", - "WHAT A SHIT OF GAME IS THIS IN WHICH THE PROTAGONIST DIES!", - "HEY, WAIT A SECOND!, WHAT ABOUT MY LAST WISH?", - "HA. HA, I'M NOW IMMUNIZED AGAINST YOU DAMNED EVIL!. THIS CIGARETTE IS AN ANTI-VAMPIRE BREW THAT VON BRAUN GAVE TO ME", - "YES SURE, BUT YOU'LL NEVER GET ME TO GIVE YOU THE RECIPE", - "APART FROM CREATING TORTURE, I CAN ALSO STAND IT.", - "OH, NO PLEASE! I'LL TALK, BUT PLEASE, DON'T DO THAT TO ME!", - "ALL RIGHT THEN. I TOLD YOU WHAT YOU WANTED TO KNOW. NOW SET B.J. AND ME FREE AND LEAVE US ALONE!", - "WHAT ARE YOU DOING HERE B.J.?. WHERE IS DRASCULA?", - "WHAT A MEAN GUY!. JUST BECAUSE HE BELONGS TO THE NOBILITY HE THINKS HE IS ENTITLED TO SLEEP WITH ANYBODY HE FEELS LIKE", - "DOWN WITH ARISTOCRATIC DESPOTISM!!", - "POOR PEOPLE OF THE WORLD FOR EVER..!!", - "AND AS I CAN SEE HE HAS CHAINED YOU UP WITH LOCKS AND ALL THAT STUFF, HUH?", - "WELL, ALL RIGHT. DO YOU HAVE A HAIRPIN OVER THERE?", - "ALL RIGHT, OK, DON'T GET MAD. I'LL THINK ABOUT SOMETHING", - "YOU...BARTENDER!!", - "HOW IS THE GAME GOING?", - "WHO?", - "CAN'T YOU SEE DRASCULA IS HERE?", - "THEN, LET'S END UP WITH HIM, RIGHT?", - "GIVE ME A SCOTCH ON THE ROCKS", - "NOTHING, I JUST FORGOT WHAT I WAS GOING TO SAY...", - "EITHER YOU GET ME A SCOTCH ON THE ROCKS OR I'LL PLAY THE PIANO UNTIL THE GAME IS OVER", - "WHEN IS THE MATCH GOING TO BE OVER?", - "GOOD EVENING", - "AND SO IGOR, HOW ARE YOU FEELING...A LITTLE HUMPED...?. HA, HA, HA, THAT WAS FUNNY!", - "WHAT ARE YOU SUPPOSED TO BE DOING?", - "WELL, NO", - "THEN WEAR GLASSES", - "WHAT IS ALL THAT ABOUT THE SUPERNATURAL ORGY?", - "OK, OK, STOP IT. I THINK I CAN GET THE PICTURE", - "COULDN'T YOU TELL ME WHERE DRASCULA IS?", - "OH...PLEASE...COME ON...!", - "WHY NOT?", - "OH...BUT DIES HE SLEEP AT NIGHT?", - "WELL, I HOPE YOU GET LUCKY", - "I HAVE TO TALK TO HIM...", - "YOOUUU...SKELETOOOONN..!!!", - "GOOD HEAVENS!, IT'S A DEAD MAN TALKING!", - "TELL HOW DID YOU GET TO END UP HERE", - "AND WHY WOULD DRASCULA WANT TO CREATE A MONSTER?", - "WHAT'S YOUR NAME, MY SKELETON FRIEND?", - "HEY, DON'T YOU WANT ANYTHING TO EAT?", - "I BET YOUR STOMACH IS PRETTY EMPTY...HA, HA,HA!", - "THE THING IS THAT I DON'T FEEL LIKE TALKING RIGHT NOW", - "I HOPE SOMEONE F...(WHISTLE) YOU...,AND YOUR F...(WHISTLE) SON OF (WHISTLE TWICE)", - "I REALLY LOVED HER. I KNOW SHE WASN'T MUCH OF A WONDER, BUT NOBODY'S PERFECT, RIGHT?", - "BESIDES. SHE REALLY HAD ONE OF THOSE GREAT BODIES THAT YOU NEVER FORGET...", - "I'LL NEVER BE THE SAME AGAIN. I WILL SHUT MYSELF AWAY IN A MONASTERY, AND WILL LET MY LIFE JUST FLOW...", - "NOTHING WILL GET ME OUT OF THIS MYSTERY BECAUSE...", - "WHOSE?. WHOSE?", - "I WANT TO BECOME A PIRATE", - "I WANT TO BECOME A PROGRAMMER", - "TELL ME SOMETHING ABOUT PELAYO", - "I'LL JUST GO ON PLAYING, AND I'LL FORGET I SAW YOU", - "WHOSE STUPID IDEA COULD THIS BE?", - "IT'S LIKE MY GRANDMOTHER'S HANDBAG ", - "JESUS, AREN'T I JUST REALLY COOL MAN...!", - "THE MORE I SEE MYSELF, THE MORE I LOVE ME", - "HOW DO I LOCK MYSELF THEN?", - "I'LL HAVE TO OPEN ME FIRST, RIGHT?", - "I'M ALL RIGHT WHERE I AM", - "I GOT ME", - "HI, MYSELF!", - "I'LL WEAR THEM WHEN THE RIGHT TIME COMES", - "I CAN'T SEE ANYTHING SPECIAL ABOUT IT", - "IT'S ALL RIGHT WHERE IT IS", - "AND WHAT FOR?", - "I CAN'T", - "HI, YOU!", - "IT'S UNCLE DESIDERIO'S PANTHEON!", - "YOOUU...UNCLE DESIDERIOOOO!!", - "NO, I DON'T WANT TO CUT MYSELF AGAIN", - "AHHH,,,EXCUS....", - "JAMM. AHH...", - "YES...WOF, WOF", - "LOOK, THERE'S A PIECE OF BUBBLE GUM STUCK HERE", - "THIS IS THE PORTABLILINE I GOT LAST CHRISTMAS", - "IT'S VERY HIGH!", - "COME OUT TO THE BALCONY MY JULIET!!", - "YOU ARE THE LIGHT THAT ILLUMINATES MY WAY!", - "HEY, DOOR!, WHAT'S THE MATTER?", - "YOOOUU, CIGARETTE SPENDING MACHINEEE!", - "IT'S A CIGARETTE SPENDING MACHINE", - "I HAVE ANOTHER COIN INSIDE", - "NO, I JUST DECIDED TO QUIT SMOKING AND DRINKING ALCOHOL", - "I WILL DEVOTE MYSELF TO WOMEN FROM NO ON", - "THIS IS A TRICK! NOTHING CAME OUT!", - "AT LAST!", - "JUST A TRUNK", - "HELLO TRUNK, YOUR NAME IS JUST LIKE MY COUSIN FRANK...", - "I'VE FOUND B.J.'S HANDBAG!", - "OH MY GOD! DON'T GET MY IMAGE REFLECTED! I'M A VAMPIRE!", - "OH...JESUS, IT'S JUST A DRAWING!", - "LITTLE MIRROR, TELL ME, WHO IS THE MOST BEAUTIFUL IN THE WHOLE KINGDOM?", - "HE WON'T OPEN", - "ALL RIGHT. I GOT THE EAR-PLUGS ON", - "IT'S A VAMPIRE'S HUNTER DIPLOMA, OFFICIALLY APPROVED BY OXFORD UNIVERSITY", - "NOT YET. THERE ARE STILL SOME INGREDIENTS MISSING. IT'S NOT WORTH WAKING HIM UP", - "BUT I DON'T HAVE MONEY", - "IT'S A BRITISH LAMP", - "HELP ME OUT HERE BARTENDER!!", - "A VAMPIRE CAME IN AND TOOK MY GIRLFRIEND AWAY!!", - "BUT, AREN'T YOU GOING TO HELP ME!!??", - "DEAD?, WHAT DO YOU MEAN DEAD?", - "AAHH....", - "A VAMPIRE HAS KIDNAPPED THE GIRL IN ROOM 501", - "BUT YOU HAVE TO HELP ME OUT!", - "CAN'T YOU PLAY ONE FROM BLUR?", - "HOW CAN YOU STAY HERE ALL DAY PLAYING THE SAME SONG ALL THE TIME?", - "AND THEN, HOW CAN YOU HEAR ME?", - "PLEASE, LEND ME THE ERA-PLUGS", - "COME ON, I'LL GIVE THEM BACK TO YOU RIGHT AWAY", - "COOOMEE OONNN...", - "WELL GOODBYE, I HAVE TO KILL A VAMPIRE", - "", - "WHAT'S YOUR LANGUAGE, TRASILVANIAN?", - "WHO IS UNCLE DESIDERIO?", - "BUT, WHAT'S THE MATTER WITH THAT DRASCULA?", - "WHO IS THAT GUY NAMED VON BRAUN?", - "AND WHY DOESN'T HE DO IT?", - "AND WHERE CAN I FIND VON BRAUN?", - "WELL, THANKS AND GOODBYE. HOPE YOU SLEEP IT OFF JUST FINE", - "WE'D BETTER CALL FIRST", - "ARE YOU PROFESSOR BRAUN?", - "AND COULD YOU TELL ME WHERE I CA...?", - "I DON'T BELIEVE HE IS GANIMEDES THE DWARF", - "PROFESSOR!!", - "PLEASE HELP ME!. THE LIFE OF MY GIRLFRIEND DEPENDS ON YOU!!", - "WELL, ALL RIGHT. I DON'T NEED YOUR HELP", - "ALL RIGHT. I'M LEAVING", - "DON'T DE AFRAID. WE WILL BEAT DRASCULA TOGETHER", - "THEN WHY DON'T YOU HELP ME?", - "I GOT THEM", - "YES, I GOT THEM!!", - "ALL RIGHT", - "AHH....YES", - "I HAVE COME TO GET INTO THAT CABIN AGAIN", - "I AM READY TO FACE YOUR TEST", - "ALL RIGHT OLD MAN. I CAME FOR MY MONEY", - "NO, NOTHING. I WAS JUST LEAVING", - "SORRY...", - "DO YOU LIKE THIS BOOK?. IT HAS SOME SCORES FROM TCHAIKOWSKY", - "HOW CAN I KILL A VAMPIRE?", - "HAS ANYBODY TOLD YOU THAT SLEEPING IN A BAD POSITION IS NOT GOOD FOR YOU?", - "THAT'S WHAT MY MUM ALWAYS TELL ME", - "WHY WOULDN'T DRASCULA KILL YOU?", - "AND WHAT WAS IT?", - "GREAT! YOU HAVE AN IMMUNIZING BREW", - "SO?", - "ALL RIGHT", - "CAN YOU REPEAT WHAT I NEED FOR THAT BREW", - "WELL, I'LL RUSH OUT TO GET IT", - "HEY, WHAT HAPPENED WITH THE PIANIST?", - "I HAVE ALL THE INGREDIENTS OF THAT BREW", - "JUST A QUESTION. WHAT IS ALL THAT ABOUT THE ALUCSARD ETEREUM?", - "HELLO, HELLO...", - "AND WHERE IS THAT CAVERN?", - "WHAT HAPPENS? DIDN'T YOU HAVE TO GO TO THE COURT?", - "...BUT... IF I MEET MORE VAMPIRES?", - "IT'S A VAMPIRE THAT DOESN'T LET ME COME THROUGH", - "HE LOOKS LIKE YODA, BUT A LITTLE TALLER", - "HEY YODA, IF YOU JUST LET ME GO ON MY WAY, I'LL GIVE YOU A PENNY", - "OK, OK, YOU GET MAD ABOUT NOTHING MAN", - "HAS ANYBODY TOLD YOU THAT YOU LOOK LIKE YODA?", - "HI VAMPIRE, IT'S A BEAUTIFUL NIGHT, HUH?", - "ARE YOU A VAMPIRE OR AN OIL PAINTING?", - "I'D BETTER NOT SAY ANYTHING, IN CASE YOU GET MAD", - "IT'S LOCKED", - "THE MAGPIE WOULD STICK OUT MY EYES IF I TRIED!", - "OH MY GOD. IT'S LOCKED...THAT'S SCARY, HUH?", - "THE HINGES ARE RUSTY", - "THERE IS ONLY ONE CAN OF FLOUR IN THERE", - "THAT TOOK AWAY THE RUST", - "I HAVE FOUND A PINE STICK", - "I'LL TAKE THIS THICKER ONE", - "WELL, I THINK I CAN GET RID OF THIS STUPID DISGUISE", - "\"PASSAGE TO TOWERS CLOSED FOR REPAIRS. PLEASE USE MAIN ENTRANCE. SORRY FOR THE INCONVENIENCE\"", - "...HE IS PALE, HE HAS FANGS AND WEARS A TOUPE\220 AND HE SURE IS DRASCULA!", - "IT'S B.J.! ARE YOU ALL RIGHT B.J.?", - "YES, I KNOW SHE IS STUPID, BUT I'M SO LONELY", - "YOU DON'T HAVE A KEY AROUND THERE, DO YOU?", - "I BET YOU DON'T HAVE A PICKLOCK AROUND!", - "GIVE ME A HAIRPIN, I'M GOING TO PLAY MCGYVER HERE!", - "DON'T GO ANYWHERE. I'LL BE RIGHT BACK", - "SHOOT! IT'S BROKEN!", - "OLEEEE! I EVEN SHAVED DUDE!", - "YES, DARLING?", - "HE'S NOT ARRIVED YET", - "THE PIANIST IS NOT HERE", - "A TRANSYLVANIAN SCOTCH ON THE ROCKS", - "I DON'T HAVE A ROOM YET", - "IT LOOKS LIKE HE GOT STUCK IN THE BATH AND DECIDED TO RUN A BAR", - "HE WAS DRUNK AS A SAILOR", - "THAT HAIR...REMINDS ME OF SOMEBODY", - "IT'S A RAW-BONED SKELETON", - "LOOK! THERE'S MIGUEL BOSE!", - "HE'S ASLEEP. IT'D BE A SHAME WAKING HIM UP", - "HE'S UGLIER THAN EMILIO DE PAZ", - "A PINE-WOODEN COFFIN", - "HE IS GOING TO CUT ME IN LITTLE SLICES. JUST LIKE A SAUSAGE", - "I DON'T LIKE PENDULAE. I'D RATHER PREFER ARTICHOKES", - "I CAN'T MAKE IT. I'M HANDCUFFED", - "IT'S OBVIOUSLY A SECRET DOOR", - "THEY IGNORE ME", - "COME ON..!", - "WHEN I READ THE SCRIPT IT WAS SUPPOSED TO MOVE, BUT THE BUDGET GOT CRAZY AND THEY COULDN'T AFFORD TO PAY THE GYM, SO THAT I NEVER GOT TOUGH. END OF STORY", - "IT SEEMS A LITTLE LOOSE FROM THE WALL", - "I DON'T THINK IS GOING TO HELP ME ANYWAY. IT'S TOO WET TO LIGHT IT", - "TO WEST WING? NO WAY! NOBODY KNOWS WHAT YOU CAN FIND THERE!!", - "SHE'S GOT NICE TRANSILVANIAN REASONS", - "", - "IT'S A SHAME THERE ISN'T A ROASTED LAMB IN THERE", - "LAST TIME I OPENED AN OVEN I BLEW UP THE HOUSE", - "THAT'S THE TRANSILVANIAN FOOTBALL BADGE", - "WHAT FOR? TO PUT IT ON MY HEAD", - "I DON'T THINK THESE TOWERS ARE THE OPENING KIND", - "I DON'T WANT TO KNOW WHAT KIND OF FOOD IS IN THERE!", - "IT LOOKS IMPRESSIONIST TO ME...", - "THE NIGHT IS FALLING OVER ALL OF US...THAT'S SCARY, ISN'T IT?", - "IT'S STUCK!", - "IT'S THE KING. YOU DIDN'T IMAGINE THAT, DID YOU!", - "NO, I ALREADY HAVE ONE AT HOME TO FEED", - "A SHELF WITH BOOKS AND SOME OTHER THINGS", - "BUT WHO CAN I CALL AT THIS TIME?", - "\"HOW TO MAKE THE TAX RETURN FORMS\". HOW INTERESTING!", - "I ALREADY HAVE ONE AT HOME. I THINK IT'S A WORLDWIDE BEST SELLER", - "A COMPLETELY NORMAL KEY", - "I THINK SHE IS NOT FROM AROUND HERE", - "HEY, THEY'RE FANG-LIKE FRENCH FRIES! I LOVE IT!", - "I DON'T THINK THIS IS THE RIGHT TIME TO EAT THAT CRAP KNOWING THAT MY GIRLFRIEND HAS BEEN KIDNAPPED BY THE MOST EVIL PERSON EVER ON EARTH", - "I'M HAVING A GREAT TIME KILLING VAMPIRES WITH THIS THING!", - "LET'S SEE IF ANOTHER ONE COMES SOON!", - "NO, IT HAS TO BE WITH A DIRTY AND STINKY VAMPIRE, JUST LIKE THE ONE I KILLED BEFORE", - "THIS IS THE ONE AND ONLY WIG ELVIS USED WHEN HE GOT BALD", - "IT'S FLOUR, BUT DON'T ASK ME ANY COMMERCIAL NAMES", - "MAYBE ANOTHER TIME, OK?", - "THAT'S A GREAT AXE, IT'S A SHAME THERE IS NO VAMPIRE'S HEAD AROUND HERE, HUH?", - "NO. I'M REALLY A GOOD PERSON", - "IT'S MARGARET'S THATCHER DEODORANT...HA, HA, HA...!!", - "THAT'S A PRETTY CUTE CLOAK", - "", - "JUST LIKE ALL BRANCHES FROM ANY TREE IN THE WORLD, THERE IS NOTHING SPECIAL.", - "HEY, THAT'S AMAZING! A ROPE WITHIN THIS TYPE OF ADVENTURE!", - "I WONDER WHAT WE COULD USE IT FOR...", - "A ROPE TIED TO A BRANCH OR THE OTHER WAY AROUND, HOWEVER YOU WANT TO PUT IT...", - "IT LOOKS LIKE THIS MAGPIE IS EVIL-MINDED", - "FORGET IT, I'M NOT SAYING ANYTHING IN CASE HE GETS MAD", - "SHE LOOKS DEAD, BUT SHE REALLY ISN'T, HUH?", - "NO ANIMAL WAS HARMED DURING THE PRODUCTION OF THIS GAME", -}, -{ - "", - "Es la segunda puerta mas grande que he visto en mi vida", - "Bueno, no", - "Esta sellada con tablones. La iglesia debe llevar abandonada varios a\244os", - "Si no la he abierto", - "\250Que hago? \250La arranco?", - "Hola puerta. Te voy a hacer un marco.", - "Demasiado para mi.", - "una ventana sellada con tablones.", - "No puedo.", - "Ya lo esta.", - "\250Y pa que?", - "Hola ventana. \250Tienes algo que hacer esta noche?", - "No sin el permiso de obras publicas", - "\255eh! esa ventana tiene solo un tablon...", - "\255Eoooooo! \255Ventana!", - "Hola tu.", - "", - "No alcanzo.", - "Esta bien donde esta.", - "", - "Es una tumba en forma de cruz.", - "No gracias.", - "Hola muerto. \250quieres gusanitos?", - "Si hombre. Como en Poltergueist.", - "", - "", - "Vuelvo en quince minutos.", - "Prohibido pegar carteles.", - "", - "Esta cerrado con llave.", - "Ya tengo uno.", - "", - "No contesta.", - "No, esta bien aparcado.", - "Es una puerta.", - "Un cajon de la mesa.", - "Un sospechoso armario.", - "Hola armario. \250Que tal?", - "", - "", - "Es un candelabro muy viejo.", - "Debe de llevar aqui desde que Mazinguer-z era un tornillo.", - "No. Es una reliquia.", - "Es un bonito retablo.", - "", - "Ji, ji, ji.", - "", - "No.", - "", - "Ja, ja, ja. \255que bueno!", - "", - "", - "", - "No veo nada en especial.", - "Es Fernan, la planta.", - "Es una de las picas de la verja.", - "\255Eh! Aqui debajo hay una caja de cerillas.", - "\255Mira! un paquete de clinex. \255Y hay uno sin usar!", - "No hay nada mas en el cubo.", - "Es un ciego que no ve.", - "", - "", - "", - "", - "Es una cuantiosa cantidad de dinero.", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NO TIENE NADA DE ESPECIAL", - "NO ES NADA FUERA DE LO NORMAL", - "\250QUE PASA TU?", - "HOLA", - "\250NADA NUEVO?", - "\250QUE TAL LA FAMILIA?", - "\255QUE COSAS TIENES!", - "\255PERO COMO VOY A COGER ESO!", - "MI RELIGION ME LO PROHIBE", - "MEJOR NO", - "\255SI HOMBRE!", - "NI HABLAR DE ESO", - "IMPOSIBLE", - "ESTO NO SE ABRE", - "YO SOLO NO PUEDO", - "SI QUISIERA PODRIA, PERO ES QUE ME DA PEREZA", - "NO LE VEO MOTIVO APARENTE", - "ES UN CEREBRO BASTANTE MAJO", - "Y BIEN, CEREBRO \250QUE PIENSAS HACER ESTA NOCHE?", - "NO, DEBE CONSERVARSE EN LUGAR CERRADO A LA ACCION MUTANTE DE LA ATMOSFERA", - "ES UN HUESO, COMO MI JEFE", - "UNA ESTACA MUY AFILADA", - "FIEL ESTACA PUNTIAGUDAAA, NOBLE ROBLE TRANSILVAAANOO", - "\255VAYA, ME TENGO QUE CORTAR LAS U\245AS!", - "\255AHI DENTRO ESTA B.J., Y HAY QUE VER COMO ESTA LA TIA!", - "ESTA CERRADA A CAL Y CANTO", - "\"CANDADOS CAL Y CANTO S.A.\"", - "ES EL TIPICO ESQUELETO QUE ESTA EN TODAS LAS MAZMORRAS DE TODOS LOS JUEGOS", - "SE SUELE USAR PARA COMUNICAR CORRIENTE ELECTRICA A LOS APARATOS A EL ENCHUFADOS", - "ES TOTALMENTE ARTESANAL, PORQUE LOS JAPONESES LOS HACEN DE BOLSILLO", - "SOLO HE VISTO EN MI VIDA OTRA COSA TAN FEA", - "QUITA. NO LE DIGO NADA A VER SI SE VA A ENFADAR", - "PARECE BASTANTE RACIONAL", - "ES UNA FOTO DE PLATON ESCRIBIENDO SU DIALOGO PERDIDO", - "NO SOY DE LOS QUE HABLAN CON POSTERS", - "UN ESCRITORIO MUY MONO", - "ES UN DIPLOMA DE CAZA-CAZA-VAMPIROS HOMOLOGADO POR LA UNIVERSIDAD DE OXFORD", - "ES NOCHE CERRADA CON LUNA LLENA", - "PARECE QUE ESTOS TORNILLOS NO ESTAN MUY ENROSCADOS", - "NO MIRES, PERO CREO QUE UNA CAMARA OCULTA ME ESTA ENFOCANDO", - "UN DETECTOR DE ESTACAS MUY MODERNO", - "NO, EL LABORATORIO ESTA EN EL SEGUNDO PISO", - "UNA BONITA MESILLA DE NOCHE", - "ES UN MONTON DE DINERO QUE NO PUEDE FALTAR EN UNA AVENTURA QUE SE PRECIE", - "SI YO FUERA RICO, DUBIDUBIDUBIDUBIDUBIDUBIDUBIDU", - "SON UNAS EXTRA\245AS HOJAS. DEBEN DE HABERLAS TRAIDO DE SUDAMERICA, O POR AHI", - "NO CREO QUE ME CONTESTARAN", - "ES UN BONITO CRUCIFIJO DE MADERA. EL ICONO NO CAPTA TODA LA EXTENSION DE SU BELLEZA", - "YO SOLO REZO ANTES DE ACOSTARME", - "\255EH, PARECE QUE ESTA PICA ESTA UN POQUITO SUELTA!", - "PARA QUE LUEGO TE QUEJES DE QUE NO DOY PISTAS", - "ES UNA PICA BASTANTE CONVENCIONAL", - "SON MONOS, AUNQUE TIENEN UN POCO DE MIERDECILLA", - "NO, NO ME OIRIAN. JI,JI,JI \255QUE BUENO!", - "\"LA BELLA DURMIENTE DEL BOSQUE\" DE CHAIKOSKY, O CHOIFRUSKY, O COMO SE DIGA", - "MUY APETITOSO", - "NO, YO NO SOY DE ESOS QUE SE METEN EN LA BOCA CHICLES USADOS", - "UNA HOZ MUY MONA. ME PREGUNTO DONDE ESTARA EL MARTILLO", - "\"LOS FABRICANTES DE TABACO ADVIERTEN QUE LAS AUTORIDADES SANITARIAS PERJUDICAN SERIAMENTE LA SALUD\"", - "UNA VELA NORMAL Y CORRIENTE, CON CERA Y TODO", - "\255HAY QUE VER COMO BRILLAN ESTAS DOS BRILLANTES MONEDAS!", - "\255HAY QUE VER COMO BRILLA ESTA BRILLANTE MONEDA!", - "CON ESTO SERE INMUNE A LAS MORDEDURAS DE LOS VAMPIROS", - "NO, TODAVIA NO ES EL MOMENTO", - "HAY UN BILLETE DE MIL Y UN PAR DE MONEDAS", - "DICE \"SE RUEGA NO ECHAR COMIDA AL PIANISTA\"", - "TORTILLA, 200. PESCAITOS FRITOS, 150, PATATAS ALIOLI, 225", - "LAS MEJORES HAMBUERGUESAS A ESTE LADO DEL DANUBIO, POR SOLO 325", - "ES UNA BONITA CALAVERA, CON UNA MIRADA MUY PENETRANTE. \255JI, JI, JI, QUE BUENO!", - "HOLA CALAVERA, ME RECUERDAS AL TIO DE HAMLET", - "TENGO POR COSTUMBRE NO TOCAR COSAS QUE HAYAN ESTADO VIVAS", - "ES UNA PAPELERA", - "ES UNA PORRA PARA EL PARTIDO DE ESTA NOCHE", - "ME PREGUNTO QUE HABRA DETRAS", - "\255EH, ESTA CORTINA NO SE MUEVE!", - "HAY QUE VER, QUE TETRICO ES ESE CASTILLO, \250EH? ", - "NO PUEDO, ESTA DEMASIADO LEJOS PARA OIRME", - "ES UN TIPICO BOSQUE TRANSILVANO, CON ARBOLES ", - "\255PERO QUE TONTERIAS DICES, CON LO OSCURO QUE ESTA!", - "CONFITERIA GARCIA. PASTELES Y CHICLES.", - "UNA PUERTA MUY BONITA", - "ESTA CERRADA", - "UN BARRIL COMPLETAMENTE CERRADO", - "", - "\255QUE BICHOS MAS MONOS!", - "BSSST, BSSST, GATITO...", - "NO CONTESTA", - "LA LUNA ES UN SATELITE QUE GIRA ALREDEDOR DE LA TIERRA CON UN PERIODO DE REVOLUCION DE 28 DIAS", - "HOLA, LUNA LUNERA CASCABELERA ", - "ESTA TOTALMENTE TAPIADA CON TABLONES", - "IMPOSIBLE. ESTO NO LO ABRE NI EL MAYORDOMO DE LA TELE", - "\255EH, PARECE QUE LA SOMBRA DE ESE CIPRES ES ALARGADA!", - "\255EOOO, TABERNEROOO!", - "QUISIERA UNA HABITACION ", - "\250SABE DONDE PUEDO ENCONTRAR A UN TAL CONDE DRASCULA?", - "SI, \250QUE PASA? ", - "\250Y ESO?", - "\250DE... DE VERDAD?", - "BUENA PREGUNTA, LE VOY A CONTAR MI HISTORIA, MIRE...", - "SON SOLO CINCO MINUTOS", - "ME LLAMO JOHN HACKER, Y SOY REPRESENTANTE DE UNA INMOBILIARIA BRITANICA", - "AL PARECER, EL CONDE DRASCULA QUIERE COMPRAR UNOS TERRENOS EN GIBRALTAR, Y ME HAN MANDADO A MI PARA NEGOCIAR LA VENTA", - "PERO ME PARECE A MI QUE MA\245ANA TEMPRANITO ME VUELVO CON MI MAMA", - "BONITA NOCHE \250VERDAD?", - "NO, NADA", - "EOOOO, PIANISTA", - "BONITA NOCHE", - "Y ADEMAS NO HACE FRIO", - "PUES NADA, TE DEJO QUE SIGAS TOCANDO", - "PUES ESO", - "HOLA JEFE, \250QUE TAL?", - "\250Y LA FAMILIA?", - "HAY AMBIENTE AQUI \250EH?", - "MEJOR NO DIGO NADA", - "SE ESTA MEJOR EN CASA QUE EN NINGUN SITIO... SE ESTA MEJOR EN... \250EH? PERO SI USTED NO ES LA TIA ENMA. ES MAS. \255SI YO NO TENGO NINGUNA TIA ENMA!", - "SI, EL MIO TAMBIEN. USTED PUEDE LLAMARME COMO LE APETEZCA, AUNQUE SI ME LLAMA JOHNY, ACUDO COMO LOS PERROS", - "SI, QUE GOLPES TENGO \250VERDAD? POR CIERTO, \250DONDE ESTOY?", - "SI.", - "CACHIS... ", - "OH, SI. POR SUPUESTO", - "PUES MUCHAS GRACIAS POR PRESTARME TU AYUDA. NO TE MOLESTO MAS. SI ME DICES DONDE ESTA LA PUERTA, POR FAVOR... ", - "PORQUE EL GOLPE ME HA DEBIDO AFECTAR AL CEREBRO Y NO VEO TRES EN UN BURRO ", - "BAH, NO IMPORTA. SIEMPRE LLEVO DE REPUESTO", - "\255GUAU, QUE TIA MAS BUENA! \255NO ME HABIA DADO CUENTA YO! CLARO, SIN LAS GAFAS", - "OYE... ", - "\255\250 Y ESTOOOOOO?!", - "\255NO TE PREOCUPES B.J., AMOR MIO! TE SALVARE DE LAS GARRAS DE ESE ", - "ME HA TOCADO LAS NARICES, VAMOS.", - "\255AHHH, UN HOMBRE LOBO! \255MUERE MALDITO!", - "SI, ESTO...", - "SI, ESTO... CREO QUE SEGUIRE MI CAMINO. CON PERMISO... ", - "\250QUE?", - "PUES LA VERDAD, PENSANDOLO BIEN... CREO QUE NO", - "DIME, OH ERUDITO FILOSOFO, \250EXISTE ALGUNA RELACION CAUSA-EFECTO ENTRE LA VELOCIDAD Y EL TOCINO?", - "VALE, VALE, DEJALO. DE TODAS FORMAS, NO SE POR QUE HE DICHO ESO.", - "\250QUE HACES AQUI FILOSOFANDO, QUE NO TE ESTAS COMIENDO GENTE?", - "\250Y ESO?", - "OYE, PUEDES REPETIR ESO DE \"INCLINACIONES PRE-EVOLUTIVAS\"?", - "SI HOMBRE. ESE ROLLO QUE ME HAS SOLTADO ANTES. ES QUE NO ME HE ENTERADO MUY BIEN...", - "NO, MEJOR NO DIGO NADA, QUE COMO LE TOQUE LA VENA...", - "\250SI, DIGA?", - "SI, \250QUE PASA? ", - "AH, PUES AHORA QUE SACA EL TEMA LE DIRE QUE...", - "", - "POR CIERTO, \250QUE PASARIA SI UN VAMPIRO SE HICIERA CIRCUNSTANCIALMENTE CON LA RECETA... ", - "PUES NADA. OYE, \250A QUE ESTO PARECE UN PEGOTE PUESTO EN EL GUION PARA ACABAR PRONTO EL JUEGO? BUENO, A LO MEJOR NO", - "\255ESTA VACIO!", - "PORQUE ME ROBASTE MI AMOR, B.J. SIN ELLA LA VIDA PARA MI NO TIENE SENTIDO", - "\255\250SU CEREBRO?!", - "PUES NO ES POR NADA, PERO ME PARECE QUE ME HA CARGADO TU MONSTRUITO", - "\255VIRGENCITA, QUE ME QUEDE COMO ESTOY!", - "\255NO TE SALDRAS CON LA TUYA. SEGURO QUE APARECE SUPERLOPEZ Y ME RESCATA!", - "VAYA UNA MIERDA DE JUEGO EN EL QUE MUERE EL PROTAGONISTA ", - "UN MOMENTO, \250QUE HAY DE MI ULTIMO DESEO?", - "\255JA, JA! AHORA ESTOY INMUNIZADO CONTRA TI MALDITO DEMONIO. ESTE CIGARRILLO ES UNA POCION ANTIVAMPIRICA QUE ME DIO VON BRAUN ", - "SI, CLARO. PERO NUNCA CONSEGUIRAS QUE TE DIGA LA RECETA", - "PUEDO SOPORTAR LA TORTURA, ADEMAS DE CREARLA ", - "\255NO, POR FAVOR! \255HABLARE, PERO NO ME HAGA ESO!", - "BUENO. YA TE HE DICHO LO QUE QUERIAS SABER. AHORA LIBERANOS A B.J. Y A MI Y DEJANOS EN PAZ", - "\255B.J.! \250QUE HACES AQUI? \250DONDE ESTA DRASCULA?", - "\255QUE DESALMADO! SOLO PORQUE PERTENECE A LA NOBLEZA SE CREE QUE TIENE EL DERECHO DE PERNADA CON CUALQUIERA QUE SE LE ANTOJE ", - "\255ABAJO LA ARISTOCRACIA CACIQUIL!", - "\255ARRIBA LOS POBRES DEL MUUNDOOO....", - "Y POR LO QUE VEO TE HA ENCADENADO CON CANDADO Y TODO", - "BUENO, VALE. \250NO TENDRAS UNA HORQUILLA?", - "BUENO, BUENO. NO TE PONGAS ASI, YA SE ME OCURRIRA ALGO.", - "EH, TABERNERO", - "\250COMO VA EL PARTIDO?", - "\250QUIEN?", - "\250ES QUE NO VES QUE ESTA AQUI DRASCULA?", - "PUES VAMOS A ACABAR CON EL \250NO?", - "PONME UN CUBATA...", - "NADA. SE ME HA OLVIDADO LO QUE TE IBA A DECIR", - "O\247ME\247PONES\247UN\247CUBATA\247O\247ME\247PONGO\247A\247TOCAR\247EL\247PIANO", - "\250CUANTO QUEDA PARA QUE ACABE EL PARTIDO?", - "BUENAS NOCHES", - "\250Y QUE TAL ANDAS IGOR? \250JOROBAO? \255JI,JI,JI, QUE BUENO! ", - "\250QUE SE SUPONE QUE HACES?", - "PUES NO", - "PUES PONTE GAFAS", - "\250QUE ES ESO DE LA ORGIA SOBRENATURAL?", - "VALE, VALE, NO SIGAS. YA ME HAGO UNA IDEA", - "\250NO PODRIAS DECIRME DONDE ESTA DRASCULA? ", - "ANDA, PORFAAA", - "\250POR QUE NO?", - "AH, PERO \250DUERME POR LA NOCHE?", - "BUENO, PUES QUE SE DE BIEN LA RENTA", - "ES QUE TENGO QUE HABLAR CON EL", - "\255EOOO, ESQUELETOOO! ", - "\255CANASTOS! \255UN MUERTO QUE HABLA!", - "CUENTAME, \250COMO HAS VENIDO A PARAR AQUI?", - "\250Y PARA QUE VA A QUERER DRASCULA CREAR UN MONSTRUO? ", - "\250CUAL ES TU NOMBRE, AMIGO ESQUELETO?", - "OYE, \250NO QUIERES QUE TE TRAIGA NADA DE COMER?", - "DEBES TENER EL ESTOMAGO VACIO. \255JI, JI, JI!", - "LA VERDAD ES QUE NO ME APETECE HABLAR AHORA", - "\255LA MADRE QUE...(PITIDO) ESPERO QUE TE...(PITIDO) Y QUE TE...(PITIDO) DOS VECES!", - "YO LA QUERIA, DE VERDAD. VALE, DE ACUERDO QUE NO ERA UNA LUMBRERA, PERO NADIE ES PERFECTO \250NO? ", - "ADEMAS, TENIA UN CUERPAZO QUE PARA QUE QUEREMOS MAS", - "YA NO VOLVERE A SER EL MISMO. ME RECLUIRE EN UN MONASTERIO A DEJAR QUE MI VIDA SE ME ESCAPE POCO A POCO", - "NADA PODRA YA SACARME DE ESTA MISERIA PORQUE...", - "\250DE QUIEN? \250DE QUIEN?", - "QUIERO SER PIRATA", - "QUIERO SER PROGRAMADOR ", - "CONTADME ALGO SOBRE PELAYO", - "SEGUIRE JUGANDO Y OLVIDARE QUE OS HE VISTO ", - "\255A QUIEN SE LE HABRA OCURRIDO ESTA IDIOTEZ!", - "ES UN BOLSO COMO EL DE MI ABUELITA ", - "\255PERO QUE BUENO QUE ESTOY!", - "CUANTO MAS ME MIRO MAS ME GUSTO", - "\250Y LUEGO COMO ME CIERRO?", - "TENDRE QUE ABRIRME PRIMERO \250NO?", - "ESTOY BIEN DONDE ESTOY", - "YA ME TENGO", - "HOLA YO", - "ME LOS PONDRE CUANDO LA OCASION SEA OPORTUNA", - "NO VEO NADA EN ESPECIAL", - "ESTA BIEN DONDE ESTA", - "\250Y PA QUE?", - "NO PUEDO", - "HOLA TU", - "ES EL PANTEON DEL TIO DESIDERIO", - "\255EOOOO, TIO DESIDERIOOOO!", - "NO. NO QUIERO CORTARME OTRA VEZ", - "\255EJEM,JEM...!", - "\255YAMM, EMMM, JH!", - "\255SI, COF,COF!", - "ANDA, SI HAY UN CHICLE AQUI PEGADO", - "ES EL MOVILANI QUE ME REGALARON EN NAVIDAD", - "\255QUE ALTO ESTA!", - "\255SAL AL BALCON JULIETA!", - "\255TU ERES LA LUZ QUE ILUMINA MI CAMINO!", - "EH,PUERTA \250QUE PASSA?", - "EOOO, MAQUINA DE TABACO DE TRANSILVANIAAA", - "ES UNA MAQUINA EXPENDEDORA DE TABACO", - "TENGO OTRA MONEDA DENTRO", - "NO. HE DECIDIDO DEJAR EL TABACO Y EL ALCOHOL ", - "A PARTIR DE AHORA ME DEDICARE SOLO A LAS MUJERES ", - "\255ESTO ES UN TIMO! NO HA SALIDO NADA", - "\255POR FIN! ", - "PUES ESO, UN BAUL", - "HOLA BAUL, TE LLAMAS COMO MI PRIMO QUE SE LLAMA RAUL.", - "HE ENCONTRADO EL BOLSO DE B.J.", - "DIOS MIO, NO ME REFLEJO \255SOY UN VAMPIRO!", - "...AH, NO. ES QUE ES UN DIBUJO", - "ESPEJITO: \250QUIEN ES EL MAS BELLO DEL REINO?", - "NO ME QUIERE ABRIR", - "MUY BIEN. ME HE PUESTO LOS TAPONES", - "ES UN DIPLOMA DE CAZA-VAMPIROS HOMOLOGADO POR LA UNIVERSIDAD DE CAMBRIDGE", - "NO, AUN ME FALTAN INGREDIENTES, NO VALE LA PENA DESPERTARLE", - "ES QUE NO TENGO DINERO", - "ES UNA LAMPARA BRITANICA", - "\255TABERNERO! \255AYUDEME!", - "HA APARECIDO UN VAMPIRO Y SE HA LLEVADO A MI NOVIA", - "\255\250PERO NO VA USTED A AYUDARME?!", - "\250MUERTA? \250QUE ES LO QUE QUIERE DECIR?", - "\255EJEM!", - "\255UN VAMPIRO HA SECUESTRADO A LA CHICA DE LA 506!", - "\255TIENES QUE AYUDARME!", - "\250NO SABES TOCAR NINGUNA DE LOS INHUMANOS?", - "\250COMO TE AGUANTAS, TODO EL DIA TOCANDO LO MISMO?", - "\250Y ENTONCES COMO ME OYES?", - "DEJAME LOS TAPONES", - "ANDA. SI TE LOS DEVUELVO ENSEGUIDA", - "VENGAAAA...", - "ADIOS. TENGO QUE MATAR A UN VAMPIRO", - "", - "\250QUE HABLAS? \250EN TRANSILVANO?", - "\250QUIEN ES EL TIO DESIDERIO?", - "\250PERO QUE PASA CON ESE TAL DRASCULA?", - "\250QUIEN ES ESE TAL VON BRAUN?", - "\250Y POR QUE NO LO HACE?", - "\250Y DONDE PUEDO ENCONTRAR A VON BRAUN?", - "PUES GRACIAS Y ADIOS, QUE LA DUERMAS BIEN", - "SERA MEJOR LLAMAR PRIMERO", - "\250ES USTED EL PROFESOR VON BRAUN?", - "\250Y NO ME PODRIA DECIR DONDE PUEDO...?", - "NO ME CREO QUE SEA EL ENANO GANIMEDES", - "\255PROFESOR!", - "\255AYUDEME! \255LA VIDA DE MI AMADA DEPENDE DE USTED!", - "ESTA BIEN, NO NECESITO SU AYUDA", - "DE ACUERDO. ME VOY", - "NO TENGA MIEDO. JUNTOS VENCEREMOS A DRASCULA", - "ENTONCES \250POR QUE NO ME AYUDA?", - "YO LAS TENGO", - "\255SI LAS TENGO!", - "DE ACUERDO", - "...ER ...SI", - "VENGO A METERME EN ESA CABINA DE NUEVO", - "ESTOY PREPARADO PARA ENFRENTARME A SU PRUEBA", - "ESTA BIEN, VEJETE. HE VENIDO A POR MI DINERO", - "NO, NADA. YA ME IBA", - "PERDONA", - "\250TE INTERESA ESTE LIBRO? TIENE PARTITURAS DE TCHAIKOWSKY", - "\250COMO PUEDO MATAR A UN VAMPIRO?", - "\250NO TE HAN DICHO QUE ES MALO DORMIR EN MALA POSTURA?", - "PUES ES LO QUE SIEMPRE ME DICE A MI MI MADRE", - "\250POR QUE NO TE PUDO MATAR DRASCULA?", - "\250Y QUE FUE?", - "\255ESTUPENDO! \255TIENE USTED UNA POCION DE INMUNID...!", - "\250ENTONCES?", - "MUY BIEN", - "\250ME PUEDE REPETIR LO QUE NECESITO PARA ESA POCION?", - "PUES PARTO RAUDO A BUSCARLO", - "OIGA, \250QUE HA PASADO CON EL PIANISTA?", - "YA\247TENGO\247TODOS\247LOS\247INGREDIENTES\247DE\247ESA\247POCION", - "UNA PREGUNTA: \250QUE ES ESO DE ALUCSARD ETEREUM?", - "DIGA, DIGA... ", - "\250Y DONDE ESTA ESA GRUTA?", - "\250QUE PASA? \250NO TENIAIS JUZGADO?", - "...PERO ...\250Y SI ME ENCUENTRO A MAS VAMPIROS?", - "ES UN VAMPIRO QUE NO ME DEJA PASAR", - "SE PARECE A YODA, PERO MAS ALTO ", - "EH, YODA. SI ME DEJAS PASAR TE DOY UN DURO", - "BUENO VALE, QUE NO SE TE PUEDE DECIR NADA", - "HOLA VAMPIRO, BONITA NOCHE \250VERDAD?", - "\250TE HAN DICHO ALGUNA VEZ QUE TE PARECES A YODA?", - "\250ERES UN VAMPIRO O UNA PINTURA AL OLEO?", - "MEJOR NO TE DIGO NADA, NO TE VAYAS A ENFADAR", - "ESTA CERRADA CON LLAVE", - "\255LA URRACA ME PODRIA SACAR UN OJO SI LO INTENTO!", - "\255ESTA CERRADA! \255DIOS MIO, QUE MIEDO!", - "LAS BISAGRAS ESTAN OXIDADAS", - "AQUI DENTRO SOLO HAY UN BOTE CON HARINA", - "ESO HA QUITADO EL OXIDO", - "HE ENCONTRADO UNA ESTACA DE PINO", - "COGERE ESTE QUE ES MAS GORDO", - "BUENO, CREO QUE YA PUEDO DESHACERME DE ESTE ESTUPIDO DISFRAZ", - "\"PASADIZO A LOS TORREONES CERRADO POR OBRAS. POR FAVOR, UTILICEN ENTRADA PRINCIPAL. DISCULPEN LAS MOLESTIAS\"", - "...ES PALIDO, TIENE COLMILLOS, TIENE TUPE Y USA CAPA... \255SEGURO QUE ES DRASCULA!", - "\255ES B.J.! B.J. \250ESTAS BIEN?", - "SI, YA LO SE QUE ES TONTA, PERO ES QUE ESTOY DE SOLO", - "NO TENDRAS UNA LLAVE POR AHI, \250VERDAD? ", - "\250A QUE NO TIENES UNA GANZUA?", - "DAME UNA HORQUILLA. VOY A HACER COMO MCGYVER", - "NO TE MUEVAS QUE AHORA VUELVO", - "\255CACHIS! \255SE ME HA ROTO!", - "\255OLEEEE! \255Y ADEMAS ME HE AFEITADO, COLEGA!", - "\250SI, CARI\245O?", - "NO LLEGA", - "EL PIANISTA NO ESTA", - "UN CUBATA TRANSILVANO", - "AUN NO TENGO HABITACION", - "PARECE QUE SE QUEDO ATASCADO EN LA BA\245ERA Y DECIDIO PONER UN BAR", - "ESTA COMO UNA CUBA DE CUBA", - "ESE PELO... EL CASO ES QUE ME RECUERDA A ALGUIEN", - "ES UN ESQUELETO HUESUDO", - "\255MIRA! \255MIGUEL BOSE!", - "ESTA DURMIENDO. SERIA UNA PENA DESPERTARLE", - "ES MAS FEO QUE EMILIO DE PAZ ", - "UN ATAUD DE MADERA DE PINO", - "ME VA A CORTAR EN RODAJITAS, COMO A UN SALCHICHON", - "NO ME GUSTAN LOS PENDULOS. PREFIERO LAS ALCACHOFAS", - "MIS MANOS ESTAN ESPOSADAS. NO VOY A PODER", - "SALTA A LA VISTA QUE ES UNA PUERTA SECRETA", - "ME IGNORAN", - "\255ANDA YA!", - "EN EL GUION SE MOVIA, PERO EL JUEGO SE SALIO DE PRESUPUESTO Y NO PUDIERON PAGARME UN GIMNASIO PARA PONERME CACHAS, ASI QUE NADA", - "PARECE QUE ESTA UN POCO SUELTA DE LA PARED", - "NO CREO QUE ME VAYA A SERVIR DE NADA. ESTA DEMASIADO HUMEDA PARA ENCENDERLA", - "\250AL ALA OESTE? \255NI LOCO! \255A SABER QUE HABRA ALLI!", - "TIENE BONITOS MOTIVOS TRANSILVANOS ", - "", - "QUE PENA QUE AHI DENTRO NO HAYA UN CORDERITO ASANDOSE ", - "LA ULTIMA VEZ QUE ABRI UN HORNO LA CASA SALTO POR LOS AIRES", - "ES EL ESCUDO DEL EQUIPO DE FUTBOL DE TRANSILVANIA", - "\250Y PARA QUE? \250PARA PONERMELA EN LA CABEZA?", - "NO CREO QUE ESTOS CAJONES SEAN DE LOS QUE SE ABREN", - "\255NO QUIERO SABER LA COMIDA QUE HABRA AHI DENTRO!", - "ME DA LA IMPRESION DE QUE ES IMPRESIONISTA", - "LA NOCHE SE APODERA DE TODOS... QUE MIEDO \250NO?", - "ESTA ATRANCADA", - "ES EL REY \250ES QUE NO TE LO HABIAS IMAGINADO?", - "NO, YA TENGO UNO EN MI CASA, AL QUE LE DOY DE COMER Y TODO", - "UNA ESTANTERIA CON LIBROS Y OTRAS COSAS ", - "\250Y A QUIEN LLAMO A ESTAS HORAS?", - "\"COMO HACER LA DECLARACION DE LA RENTA\" \255QUE INTERESANTE!", - "YA TENGO UNO EN MI CASA. CREO QUE ES UN BEST-SELLER MUNDIAL ", - "UNA LLAVE COMPLETAMENTE NORMAL", - "ME PARECE A MI QUE ESTA NO ES DE AQUI", - "\255EH, SON PATATAS FRITAS CON FORMA DE COLMILLO! ME ENCANTA", - "NO CREO QUE SEA EL MEJOR MOMENTO DE PONERSE A COMER CHUCHERIAS, CON MI NOVIA EN MANOS DEL SER MAS MALVADO QUE HA PARIDO MADRE", - "\255QUE BIEN ME LO ESTOY PASANDO CARGANDOME VAMPIROS CON ESTO!", - "A VER SI APARECE OTRO PRONTO", - "NO, TIENE QUE SER CON UN VAMPIRO SUCIO Y MALOLIENTE COMO EL QUE ME CARGUE ANTES", - "ES LA AUTENTICA PELUCA QUE USO ELVIS CUANDO SE QUEDO CALVO", - "ES HARINA, PERO NO PUEDO DECIR MARCAS", - "QUIZA EN OTRO MOMENTO \250VALE?", - "ES UN HACHA MAGNIFICA, QUE PENA QUE NO HAYA POR AQUI CERCA NINGUNA CABEZA DE VAMPIRO", - "NO. EN EL FONDO SOY BUENA PERSONA", - "ES EL DESODORANTE DE LA TACHER \255JI,JI,JI!", - "ES UNA CAPA BASTANTE MONA", - "", - "COMO TODAS LAS RAMAS DE TODOS LOS ARBOLES DE TODO EL MUNDO, O SEA, SIN NADA DE PARTICULAR", - "\255OH, INCREIBLE! \255UNA CUERDA EN UNA AVENTURA GRAFICA!", - "ME PREGUNTO PARA QUE SERVIRA...", - "UNA CUERDA ATADA A UNA RAMA O UNA RAMA ATADA A UNA CUERDA, SEGUN SE MIRE", - "PARECE QUE ESTA URRACA TIENE MUY MALAS INTENCIONES", - "QUITA, YO NO LA DIGO NADA, A VER SI SE VA A ENFADAR", - "PARECE QUE ESTA MUERTA, PERO ES MENTIRA \250EH?", - "NINGUN ANIMAL DA\245ADO EN LA PRODUCCION DE ESTE JUEGO", -}, -{ - "", - "Das ist die zweitgroesste Tuer, die ich je gesehen habe !", - "Ok, stimmt nicht ganz....", - "Sie haben Bretter davorgenagelt. Die Kirche scheint seit Jahren leer zu stehen", - "Aber ich habe sie doch nicht aufgemacht!", - "Soll ich sie aufbrechen ?", - "Hallo Tuer! Ich verpasse Dir jetzt mal einen Rahmen!", - "Zuviel fuer mich !", - "ein zugenageltes Fenster", - "Ich schaff\357es nicht!", - "Schon geschafft!", - "Und wozu?", - "Hallo Fenster. Hast Du heute abend schon was vor?", - "Nicht ohne Genehmigung der Staedtischen Baubehoerde", - "hey! Das Fenster da hat nur EIN Brett...", - "Heyhooo! Fenster!", - "Hallo Du", - "", - "Ich komme nicht dran!", - "Gut so ! ", - "", - "Es ist ein Grabstein in Form eines Kreuzes.", - "Nein, danke", - "Hallo Toter. Willst Du ein paar Wuermchen?", - "Klar Mann ! Wie in Poltergeist.", - "", - "", - "Bin in einer Viertelstunde zurueck!", - "Plakate ankleben verboten", - "", - "Sie ist abgeschlossen.", - "Ich habe schon eins.", - "", - "Keine Reaktion !", - "Nein, da steht es gut !", - "Es ist eine Tuer", - "Eine Schublade vom Tisch", - "Ein verdaechtiger Schrank", - "Hallo Schrank. Alles klar?", - "", - "", - "Ein uralter Kerzenstaender", - "Der stammt wohl noch aus der Zeit als meine Ururururoma in den Kindergarten ging ", - "Nein, eine Reliquie aus vergangenen Zeiten", - "Es ist ein huebsches Altarbild", - "", - "Hi,hi,hi", - "", - "Nein.", - "", - "Ha,ha,ha! klasse!", - "", - "", - "", - "Ich sehe nichts besonderes", - "Freddy, die Topfblume", - "Eine Spitze aus dem Jaegerzaun", - "Ej! Hier unten liegt eine Streichholzschachtel!", - "Guck mal! Eine Packung Tempos! Und eins sogar ungebraucht!", - "Sonst ist nichts mehr im Eimer", - "Ein Blinder der nichts sieht", - "", - "", - "", - "", - "Ein Wahnsinnsbatzen Geld.", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "SIEHT NICHT UNGEWoeHNLICH AUS", - "SIEHT NICHT AUSSERGEWoeHNLICH AUS", - "EJ DU, WAS IST LOS?", - "HALLO", - "NICHTS NEUES?", - "WIE GEHTS DER FAMILIE?", - "WAS DU FueR SACHEN HAST !", - "ABER WIE SOLLTE ICH DAS AUFHEBEN ?", - "MEINE RELIGION VERBIETET MIR DAS", - "BESSER NICHT", - "KLAR MANN!", - "DU SPINNST WOHL !", - "UNMoeGLICH", - "GEHT NICHT AUF !", - "ALLEINE SCHAFFE ICH DAS NICHT", - "WENN ICH WOLLTE, KoeNNTE ICH, ABER ICH HABE KEINE LUST", - "ICH WueSSTE NICHT WARUM", - "EIN SCHaeDEL, DER GUT DRAUF IST", - "UND? SCHON WAS VOR HEUTE ABEND, SCHaeDEL?", - "NEIN, ER MUSS AN EINEM KueHLEN ORT GELAGERT WERDEN, FERN DER ZERSToeRERISCHEN KRAFT DER ATMOSPHaeRE", - "KNOCHENTROCKEN, WIE MEIN CHEF!", - "EIN SEHR SPITZER PFLOCK", - "GUTER SPITZER PFLOHOCK, HOLZ SO EDEL, TRANSILVAAANISCH!!!", - "OH VERDAMMT, ICH MUSS MIR DIE NaeGEL SCHNEIDEN !", - "DA DRINNEN LIEGT B.J., UND GUCK MAL WIE DIE TANTE AUSSIEHT !", - "NIET UND NAGELFEST", - " \"NIET & NAGEL GmbH & Co. KG\"", - "DAS TYPISCHE SKELETT IM TYPISCHEN VERLIESS EINES TYPISCHEN SPIELS", - "WIRD NORMALERWEISE ZUR STROMVERSORGUNG ALLER EINGESToePSELTEN GERaeTE VERWENDET", - "TOTALES KUNSTHANDWERK, WEIL SIE DANK DEN JAPANERN KLEINE MINIATUREN SIND", - "ES GIBT NUR EINS, WAS GENAUSO HaeSSLICH IST", - "HAU AB. ICH SAG IHM GAR NICHTS. MAL GUCKEN OB ER AUSFLIPPT", - "SCHEINT ZIEMLICH VERNueNFTIG ZU SEIN", - "EIN FOTO VON PLATON WIE ER SEINEN VERLORENEN DIALOG SCHREIBT", - "SEH ICH SO AUS ALS OB ICH MIT POSTERN REDE ? !", - "EIN HueBSCHER SCHREIBTISCH", - "EIN VON DER UNIVERSITaeT ZU OXFORD AUSGESTELLTES VAMPIR-JaeGER-JaeGER-DIPLOM", - "VOLLMOND IN FINSTERSTER NACHT", - "DIESE SCHRAUBEN SCHEINEN ZIEMLICH FEST ZU SITZEN", - "GUCK JETZT NICHT HIN, ABER ICH GLAUBE HIER GIBT ES EINE VERSTECKTE KAMERA", - "EIN ULTRAMODERNER PFLOCK-DETEKTOR", - "NEIN, DAS LABOR IST IM ZWEITEN STOCK", - "EIN HueBSCHES NACHTTISCHCHEN ", - "EIN BATZEN GELD DER BEI EINEM WIRKLICH GUTEN ABENTEUER NICHT FEHLEN DARF", - "WENN ICH REICH WaeRE, SCHUBIDUBISCHUBIDUBUDU ", - "KOMISCHE BLaeTTER, DIE WERDEN SIE WOHL AUS SueDAMERIKA ODER SO MITGEBRACHT HABEN .", - "ICH GLAUBE NICHT, DASS SIE ANTWORTEN WERDEN", - "EIN SCHoeNES HOLZKRUZIFIX. DEM HELDEN SIND DIE AUSMASSE SEI-NER SCHoeNHEIT NICHT GANZ KLAR.", - "ICH BETE NUR VOR DEM ZU-BETT-GEHEN", - "EJ, ICH GLAUBE, DIE SPITZE HIER IST EIN BISSCHEN LOSE !", - "UND NACHHER BESCHWERST DU DICH, ICH HaeTTE DIR KEINEN WINK GEGEBEN !", - "EINE STINKNORMALE ZAUNSPITZE", - "NIEDLICH, OBWOHL SIE EIN BISSCHEN VERDRECKT SIND", - "SIE WERDEN MICH NICHT HoeREN, HI,HI,HI, SUPERGUT !", - "DIE SCHoeNE SCHLAFENDE AUS DEM WALDE VON TSCHAIKOWSKY ODER TSCHESLOFSKY ODER WIE DER HEISST.", - "SEHR APPETITLICH", - "NEIN, SEHE ICH SO AUS, ALS WueRDE ICH BENUTZTE KAUGUMMIS KAUEN ?", - "EINE NIEDLICHE SICHEL. ICH WueSSTE NUR GERNE WO DER HAMMER IST.", - "DER GESUNDHEITSMINISTER WARNT : RAUCHEN GEFaeHRDET IHRE GESUNDHEIT", - "EINE GANZ NORMALE KERZE, MIT WACHS UND ALLEM DRUM UND DRAN", - "MAN MUSS ECHT MAL GESEHEN HABEN WIE DIESE 2 GLaeNZENDEN MueNZEN GLaeNZEN", - "MAN MUSS ECHT GESEHEN HABEN WIE DIESE GLaeNZENDE MueNZE GLaeNZT !", - "DAMIT WERDE ICH GEGEN VAMPIRBISSE IMMUN SEIN.", - "NEIN,ES IST NOCH NICHT SO WEIT", - "EIN TAUSENDER UND EIN BISSCHEN KLEINGELD", - "DA STEHT\"DEN KLAVIERSPIELER BITTE NICHT MIT LEBENSMITTELN BEWERFEN", - "CURRYWURST 3.80. POMMES FRITES 2.30., FRIKADELLEN 1.50", - "DIE BESTEN HAMBURGER DIESSEITS DER DONAU FueR NUR 3.80 DM", - "EIN SCHoeNER TOTENKOPF MIT EINEM ZIEMLICH DURCHDRINGENDEN BLICK, HI, HI, SUPERGUT !", - "HALLO TOTENKOPF, DU ERINNERST MICH AN HAMLETS ONKEL !", - "ICH HABE DIE ANGEWOHNHEIT, NICHTS ANZUFASSEN, WAS MAL LEBENDIG GEWESEN IST", - "EIN PAPIERKORB", - "SIE WETTEN, WIE DAS SPIEL HEUTE ABEND AUSGEHT", - "WAS SICH WOHL DAHINTER VERBERGEN MAG", - "EJ, DIESER VORHANG BEWEGT SICH NICHT !", - "GANZ SCHoeN GRUSELIG, DAS SCHLOSS DA, WAS ?", - "ICH SCHAFFS NICHT, ER IST ZU WEIT WEG, UM MICH ZU HoeREN", - "EIN TYPISCH TRANSSYLVANISCHER WALD, MIT BaeUMEN UND SO", - "RED KEINEN BLoeDSINN, ES IST DOCH STOCKDUNKEL!", - "KONDITOREI MueLLER. GEBaeCK UND KAUGUMMIS", - "EINE SEHR SCHoeNE TueR", - "GESCHLOSSEN", - "EINE TOTAL GESCHLOSSENE TONNE", - "", - "WAS FueR SueSSE VIECHER !", - "PSSS,PSSS,PSSS,MIETZCHEN...", - "KEINE REAKTION", - "DER MOND IST EIN SATELLIT DER DIE ERDE IN EINER UMLAUFGESCHWINDIGKEIT VON 28 TAGEN UMKREIST.", - "HALLO MOND DU KREISRUNDES MONDGESICHT", - "TOTAL MIT BRETTERN ZUGENAGELT", - "NICHTS ZU MACHEN. HIER KOMMT NOCH NICHT MAL ARNOLD S. MIT DER KREISSaeGE DURCH", - "SCHEINT SO, ALS HaeTTE DIE TANNE DA EINEN ueBERDIMENSIONALEN SCHATTEN !", - "HEHOO, WIRT !", - "SIND NOCH ZIMMER FREI ?", - "KoeNNEN SIE MIR SAGEN WO ICH EINEN GEWISSEN GRAF DRASCULA FINDE ?", - "JA, WAS GIBTS ?", - "UND WIESO ?", - "WW...WIRKLICH ?", - "GUTE FRAGE, ICH WERDE IHNEN MAL MEINE STORY ERZaeHLEN, ALSO...", - "NUR FueNF MINUTEN !", - "ICH HEISSE HEINZ HACKER UND BIN VERTRETER EINER NORDDEUTSCHEN IMMOBILIENFIRMA", - "SO WIES AUSSIEHT WILL GRAF DRASCULA EINIGE HEKTAR LAND AUF HELGOLAND KAUFEN UND ICH BIN HIER UM ueBER DIE PREISE ZU VERHANDELN", - "MMMMH, ICH GLAUBE DASS ICH MORGEN FRueH MIT MEINER MAMI ZURueCKKOMME", - "WAS FueR EINE NACHT, NICHT WAHR ?", - "NICHTS, SCHON GUT", - "HEEHOOO, KLAVIERSPIELER", - "WAS FueR EINE NACHT", - "UND ES IST AUCH GAR NICHT SO KALT", - "NUN GUT, ICH LASS DICH JETZT MAL IN RUHE WEITERSPIELEN", - "GENAU", - "HALLO CHEF, ALLES KLAR ?", - "UND DIE FAMILIE ?", - "HIER IST MaeCHTIG WAS LOS, WAS ?", - "ICH HALTE BESSER MEINEN MUND", - "ZU HAUSE IST ES IMMER NOCH AM SCHoeNSTEN...ZU HAUSE IST ES IMMER....Hae ? ABER SIE SIND DOCH NICHT TANTA ENMA. WO ICH DOCH GAR KEINE TANTE EMMA HABE !", - "JA, MEINER AUCH. SIE KoeNNEN MICH NENNEN WIE SIE WOLLEN, ICH HoeRE SELBST AUF HEINZCHEN WIE AUF KOMMANDO.", - "JA, ICH HAB GANZ SCHoeNE BEULEN, WAS ? ueBRIGENS, WO BIN ICH ?", - "JA", - "VERDAMMT.....", - "JA, KLAR, SELBSTVERSTaeNDLICH !", - "DANN ALSO VIELEN DANk FueR DEINE HILFE. ICH WERDE DICH NICHT WEITER BELaeSTIGEN. WENN DU MIR BITTE NOCH SAGEN WueRDEST, WO DIE TueR IST.... ", - "WEIL DIE BEULE WOHL MEIN GEHIRN ANGEGRIFFEN HAT UND ICH EINFACH ueBERHAUPT NICHTS SEHE", - "PAH, MACHT NICHTS. ICH HABE IMMER ERSATZ DABEI", - "WOW, WAS FueR EIN SCHARFES WEIB ! OHNE BRILLE HABE ICH DAS GAR NICHT BEMERKT !", - "EJ, DU....", - "UND WAS IST DAAAAAS ? !", - "MACH DIR KEINE SORGEN, BJ, MEINE GELIEBTE !ICH WERDE DICH AUS SEINEN KLAUEN BEFREIEN", - "ACH KOMM, ER HAT MICH AUF DIE PALME GEBRACHT", - "UUAAA, EIN WERWOLF ! KREPIER, DU MONSTER !", - "JA, DAS.... ", - "JA, DAS.... ICH GLAUB, ICH GEH DANN MAL WEITER, MIT VERLAUB...", - "WAS?", - "WENN ICHS MIR RECHT ueBERLEGE, UM EHRLICH ZU SEIN, ICH GLAUBE NEIN ", - "SAG MIR OH GEBILDETER PHILOSOPH, GIBT ES IRGENDEINEN KAUSALZUSAMMENHANG ZWISCHEN DER LICHTGESCHWINDIGKEIT und SCHINKENSPECK", - "OKAY,OKAY,VERGISS ES. ICH WEISS JEDENFALLS NICHT, WARUM ICH DAS GESAGT HABE", - "WAS PHILOSOPHIERST DU HIER HERUM, WO DU DOCH MENSCHEN FRESSEN MueSSTEST!", - "HaeH", - "EJ, KANNST DU DAS MIT DEN PRaeHISTORISCHEN NEIGUNGEN NOCHMAL ERKLaeREN ?", - "JA, MANN. DER KRAM MIT DEM DU MIR EBEN GEKOMMEN BIST. ICH HAB DAS NaeMLICH NICHT GANZ KAPIERT....", - "ICH HALTE BESSER MEINEN MUND, WEIL SOBALD ER BLUT RIECHT...", - "JA, BITTE ?", - "JA, WAS GIBTS ?", - "ACH, WO SIES GERADE ERWaeHNEN,....", - "", - "ueBRIGENS, WAS WueRDE EIGENTLICH PASSIEREN, WENN DAS REZEPT ZUFaeLLIG IN DIE HaeNDE EINES VAMPIRS GERATEN WueRDE...", - "NA WAS SOLLS. HoeR MAL, KOMMT DIR DAS NICHT AUCH WIE EIN DaeMLICHER KLEINER TRICK VOR, UM DAS SPIEL SCHNELL ZU BEENDEN ? NAJA, VIELLEICHT AUCH NICHT", - "LEER !", - "WEIL DU MIR B.J., MEINE GELIEBTE, GERAUBT HAST. OHNE SIE HAT MEIN LEBEN KEINEN SINN.", - "SEIN GEHIRN ?", - "OCH, NUR SO! ICH GLAUBE DASS ICH GENUG VON DEM KLEINEN MONSTERCHEN HABE", - "SueSSE KLEINE JUNGFRAU, ICH BLEIB SO WIE ICH BIN !", - "DAMIT KOMMST DU NICHT DURCH.. GLEICH KOMMT POPEYE UND HOLT MICH HIER RAUS !", - "WAS FueR EIN SCHEISS-SPIEL, BEI DEM DEM DER HELD STERBEN MUSS", - "HALT ! WAS IST MIT MEINEM LETZTEN WUNSCH ?", - "HAR,HAR ! JETZT BIN ICH IMMUN GEGEN DEIN VERFLUCHTES UNGEHEUER. DAS HIER IST EINE ANTI-VAMPIR-ZIGARETTE,DIE MIR VON BRAUN GEGEBEN HAT.", - "JA, KLAR. ABER ICH WERDE DIR BESTIMMT NICHT DAS REZEPT VERRATEN", - "MIT FOLTER KOMM ICH GUT KLAR, ICH DENK MIR SOGAR WELCHE AUS", - "NEIN, BITTE NICHT ! ICH SAG ALLES, ABER TUN SIE MIR DAS NICHT AN !", - "O.K. ICH HAB DIR ALLES ERZaeHLT. JETZT HOL B.J. UND MICH ENDLICH HIER RAUS UND LASS UNS IN RUHE", - "B.J. !WAS MACHST DU HIER ?WO IST DRASCULA ?", - "WAS FueR EIN MIESER TYP ! NUR WEIL ER BLAUES BLUT HAT, MueSSEN IHM NOCH LANGE NICHT ALLE JUNGFRAUEN DIESER ERDE ZU FueSSEN LIEGEN", - "NIEDER MIT DEM BONZEN-ADEL !", - "SOLIDARITaeT MIT ALLEN ARMEN DIESER WELT... !", - "UND WIES AUSSIEHT HAT ER DICH NACH ALLEN REGELN DER KUNST ANGEKETTET", - "O.K. DU HAST NICHT ZUFaeLLIG EINE HAARSPANGE ?", - "NANANA. STELL DICH NICHT SO AN . MIR FaeLLT SCHON WAS EIN.", - "HE, WIRT", - "WER GEWINNT ?", - "WER ?", - "SIEHST DU DENN NICHT, DASS HIER DRASCULA IST ?", - "NA, DANN LASS IHN UNS ALLE MACHEN, ODER ?", - "GIB MIR EINEN GIN-TONIC", - "SCHON GUT. ICH HAB VERGESSEN, WAS ICH DIR SAGEN WOLLTE", - "GIB\247MIR\247SOFORT\247EINEN\247GIN\247TONIC\247ODER\247ICH\247SPIEL\247KLAVIER", - "WIELANGE DAUERT DAS SPIEL NOCH ?", - "GUTE NACHT", - "UND WIE KOMMST DU VORAN, IGOR ? SCHLEPPEND ? HI,HI,HI, KLASSE !", - "WAS SOLL DAS SEIN, WAS DU DA MACHST?", - "NEIN", - "DANN ZIEH DIE BRILLE AUF", - "WAS SOLL DAS MIT DER ueBERNATueRLICHEN ORGIE ?", - "O.K. ES REICHT. ICH KANN ES MIR SCHON VORSTELLEN", - "KoeNNTEST DU MIR NICHT ZUFaeLLIG SAGEN, WO DRASCULA IST ?", - "ACH KOMM, BITTE, BITTE!", - "WARUM NICHT ?", - "ACH :NACHTS SCHLaeFT ER ?", - "NA, HOFFENTLICH KLAPPT DAS MIT DER EINKOMMENSERKLaeRUNG", - "ICH MUSS NaeMLICH MIT IHM REDEN", - "HEYHOO, GERIPPE !", - "VERDAMMT ! EIN SPRECHENDER TOTER !", - "ERaeHL MAL WIESO HAST DU HIER ANGEHALTEN ?", - "UND WOZU SOLLTE DRASCULA EIN MONSTER SCHAFFEN WOLLEN ?", - "WIE HEISST DU, LIEBES GERIPPE ?", - "EJ, SOLL ICH DIR NICHT VIELLEICHT WAS ZU ESSEN BRINGEN ?", - "DU HAST DOCH BESTIMMT EINEN LEEREN MAGEN, HI,HI,HI !", - "ICH HABE GERADE EINFACH KEINEN BOCK, ZU REDEN", - "FI........(BIEP) DICH DOCH IN DEIN BEFI.......(BIEP) KNIE, DU ALTER WI......(BIEP) !", - "ICH HABE SIE WIRKLICH GELIEBT, NAJA, GUT, SIe WAR WIRKLICH NICHT DIE HELLSTE VON OSRAM, ABER NOBODY IS PERFECT, STIMMTS ?", - "HEY SIE HATTE EINE WAHNSINNSFIGUR, UND WAS WILLST DU MEHR", - "NICHTS WIRD MEHR WIE VORHER SEIN. ICH WERDE INS KLOSTER GEHEN UND ELENDIGLICH DAHINSIECHEN.", - "HIER KANN MICH NICHTS UND NIEMAND MEHR RAUSHOLEN, WEIL...", - "VON WEM ? VON WEM ?", - "ICH MoeCHTE PIRAT WERDEN !", - "ICH MoeCHTE PROGRAMMIERER WERDEN !", - "ERZaeHL MIR ETWAS ueBER SIEGFRIED UND DIE NIBELUNGEN", - "ICH HAB EUCH NIE GESEHEN UND SPIEL JETZT EINFACH WEITER", - "WER HAT SICH DENN DIESEN SCHWACHSINN EINFALLEN LASSEN ?", - "EINE HANDTASCHE, WIE SIE MEINE OMI HAT", - "OH MANN, WIE GUT ICH AUSSEHE ! ", - "ICH KoeNNTE MICH GLATT IN MICH VERLIEBEN !", - "UND WIE SOLL ICH MICH ABSCHLIESSEN ?", - "ICH WERDE MICH WOHL ERSTMAL AUFSCHLIESSEN MueSSEN, WAS ?", - "HIER STEH ICH GUT", - "HAB MICH SCHON", - "HALLO ICH", - "BEI PASSENDER GELEGENHEIT WERDE ICH SIE MIR MAL REINTUN", - "ICH SEHE NICHTS BESONDERES", - "GUT SO", - "UND WIESOOO ?", - "ICH KANN NICHT", - "HALLO DU DA", - "DIE GRUFT VON ONKEL DESIDERIUS", - "HAAALLO, ONKEL DESIDEERIUUS !", - "NEIN, ICH WILL MICH NICHT SCHON WIEDER SCHNEIDEN", - "aeHEM,MMM... !", - "MMMM, LECKER,UaeaeHH !", - "JA, HUST,HUST !", - "HEY, GUCK MAL, HIER KLEBT EIN KAUGUMMI", - "DAS SUPERHANDILY DAS ICH ZU WEIHNACHTEN BEKOMMEN HABE", - "GANZ SCHoeN HOCH", - "TRITT AUF DEN BALKON, JULIA !", - "DU BIST DER STERN AN MEINEM FIRMAMENT !", - "EJ, TueR, WAS ISS LOSS ?", - "HEYHOO, TRANSSYLVANISCHES ZIGARRETTENAUTOMaeTCHEN !", - "EIN ZIGARRETTENSPENDERMASCHINCHEN", - "ICH HAB DA NOCHNE MueNZE DRIN", - "NEIN, ICH RAUCHE UND TRINKE NICHT MEHR", - "VON JETZT AN WERDE ICH MICH NUR NOCH DEN FRAUEN WIDMEN", - "BETRUG ! ES IST GAR NICHTS RAUSGEKOMMEN !", - "ENDLICH !", - "EINE TRUHE, WEITER NICHTS", - "HALLO TRUHE, DU HEISST WIE MEINE TANTE TRUDE", - "ICH HABE DIE TASCHE VON B.J. GEFUNDEN", - "MEIN GOTT, ICH SEH MICH NICHT IM SPIEGEL, ICH BIN EIN VAMPIR !", - "....ACH, NEE. ES IST NUR EIN GEMaeLDE", - "SPIEGLEIN, SPIEGLEIN AN DER WAND, WER IST DER SCHoeNSTE Im GANZEN LAND ?", - "ER MACHT MIR NICHT AUF", - "GUT. ICH HABE DIE OHRENSToePSEL DRIN", - "EIN VON DER UNIVERSITaeT ZU CAMBRIDGE AUSGESTELLTES VAMPIR-JaeGER DIPLOM.", - "NEIN, MIR FEHLEN NOCH EINIGE ZUTATEN, ES LOHNT SICH NICHT, IHN ZU WECKEN !", - "ICH HABE NaeMLICH KEIN GELD", - "EINE NORDDEUTSCHE LAMPE", - "WIRT! HELFEN SIE MIR !", - "DA STAND PLoeTZLICH EIN VAMPIR UND HAT MEINE FREUNDIN MITGENOMMEN.", - "ABER WOLLEN SIE MIR DENN NICHT HELFEN ?", - "TOT? WAS WOLLEN SIE DAMIT SAGEN ?", - "aeHEM !", - "EIN VAMPIR HAT DAS MaeDEL VON 506 ENTFueHRT !", - "DU MUSST MIR HELFEN !", - "KANNST DU KEIN BEERDIGUNGSLIED SPIELEN ?", - "WIE HaeLST DU DAS BLOSS AUS : JEDEN TAG DIE GLEICHEN LIEDER", - "AHA, UND WIE HoeRST DU MICH DANN ?", - "GIB MIR DIE OHRENSToePSEL", - "ACH KOMM, ICH GEB SIE DIR AUCH SOFORT WIEDER", - "ACH KOOOOMMM !", - "AUF WIEDERSEHEN. ICH MUSS EINEN VAMPIR ToeTEN", - "", - "REDEST DU AUF TRANSSYLVANISCH ODER WAS ?", - "WER IST ONKEL DESIDERIUS ?", - "WAS SOLL LOS SEIN MIT DIESEM GRAF DRASCULA ?", - "WER IST DIESER VON BRAUN ?", - "UND WARUM MACHT ER ES NICHT ?", - " UND WO KANN ICH VON BRAUN FINDEN ?", - "ALSO DANKE UND AUF WIEDERSEHEN, SCHLAF SCHoeN", - "WIR SOLLTeN BESSER VORHER KLINGELN", - "SIND SIE PROFESSOR VON BRAUN ?", - "UND SIE KoeNNTEN MIR NICHT VERRATEN, WO..... ?", - "ICH NEHM IHM NICHT AB, DASS ER HELGE SCHNEIDER IST", - "PROFESSOR!", - "HELFEN SIE MIR !ES GEHT UM DAS LEBEN MEINER GELIEBTEN !", - "SCHON GUT, ICH BRAUCHE IHRE HILFE NICHT", - "OK. ICH GEHE !", - "KEINE ANGST. GEMEINSAM BESIEGEN WIR DRASCULA", - "UND WARUM HELFEN SIE MIR DANN NICHT ?", - "ICH HABE SIE", - "ABER ICH HABE SIE DOCH !", - "EINVERSTANDEN", - "...aeHM,...JA", - "ICH GEHE DIREKT NOCHMAL INS AQUARIUM", - "ICH BIN SO WEIT, MICH IHREM TEST ZU STELLEN", - "SCHON GUT, ALTERCHEN. ZAHLTAG !", - "SCHON GUT. ICH WOLLTE SOWIESO GERADE GEHEN", - "TSCHULDIGE", - "WIE FINDEST DU DIESES BUCH? KLAVIERSTueCKE VON TSCHAIKOWSKY", - "WIE BRINGT MAN EINEN VAMPIR UM ?", - "HAT MAN DIR NICHT GESAGT WIE MAN SICH BETTET SO LIEGT MAN ?", - "GENAU DAS SAGT MEINE MUTTER IMMER ZU MIR", - "WARUM KONNTE DICH DRASCULA NICHT ERLEDIGEN ?", - "UND WAS DANN ?", - "SUPER ! DA HABEN SIE EIN IMMUNITaeTSMISCH.... !", - "ALSO ?", - "SEHR GUT", - "KoeNNEN SIE NOCHMAL WIEDERHOLEN WAS ICH FueR DIESE MISCHUNG BRAUCHE ?", - "DANN SATTEL ICH MAL DIE HueHNER UND BESORG ES", - "ENTSCHULDIGUNG, WO IST DER KLAVIERSPIELER ?", - "ICH\247HAB\247SCHON\247ALLE\247ZUTATEN\247FueR\247DIE\247MISCHUNG", - "EINE FRAGE : WAS SOLL DAS HEISSEN : REIPERK ALUCSARD?", - "SAGEN SIE SCHON...", - "UND WO SOLL DIESE GROTTE SEIN ?", - "WAS IST ? GABS BEI EUCH KEINE HEXENPROZESSE ?", - "...ABER WENN ICH NOCH MEHR VAMPIREN BEGEGNE ?", - "EIN VAMPIR, DER MICH NICHT DURCHLaeSST", - "ER SIEHT WIE AUS WIE JODA, NUR VIEL GRoeSSER", - "EJ, JODA. WENN DU MICH DURCHLaeSST, GEB ICH DIR ne mark", - "NA GUT, DIR KANN MAL WOHL NICHTS ERZaeHLEN", - "HALLO, VAMPIR, WAS FueR EINE NACHT, WAS ?", - "HAT MAN DIR SCHON MAL GESAGT, DASS DU AUSSIEHST WIE JODA ?", - "BIST DU EIN VAMPIR ODER EIN oeLGEMaeLDE ?", - "ICH HALT BESSER MEINEN MUND, SONST REGST DU DICH NOCH AUF", - "ABGESCHLOSSEN", - "DIE ELSTER KoeNNTE MIR EIN AUGE RAUSREISSEN, WENN ICHS VERSUCHE !", - "ZU !MEIN GOTT, WIE UNHEIMLICH !", - "DIE SCHARNIERE SIND ZUGEROSTET", - "HIER IST NUR EIN PaeCKCHEN MEHL", - "DAS HAT DEN ROST ENTFERNT", - "ICH HABE EINEN PFLOCK AUS FICHTENHOLZ GEFUNDEN", - "ICH NEHM DAS HIER, DAS IST SCHoeN DICK !", - "NA, ICH GLAUBE ICH KANN MICH JETZT MAL AUS DIESER DaeMLICHEN VERKLEIDUNG SCHaeLEN", - "EINGaeNGE ZU DEN SEITENFLueGELN WEGEN BAUARBEITEN GESPERRT. BENUTZEN SIE BITTE DEN HAUPTEINGANG", - "...ER IST BLASS, HAT KOMISCHE ZaeHNE, TRaeGT EIN TOUPET UND EINEN UMHANG...DAS MUSS DRASCULA SEIN !", - " ES IST B.J. ! B.J. ALLES O.K ?", - "ICH WEISS SCHON DASS SIE DUMM IST, ABER ICH BIN SO EINSAM", - "DU HAST BESTIMMT KEINEN SCHLueSSEL, STIMMTS ?", - "ICH WETTE, DU HAST KEINEN DIETRICH", - "GIB MIR DIE HAARSPANGE. ICH MACHS WIE MCGYVER", - "BEWEG DICH NICHT, ICH BIN SOFORT ZURueCK", - "VERDAMMT! ER IST MIR ABGEBROCHEN !", - "HEYJEYJEY !UND ICH HAB MICH AUCH RASIERT, ALTER !", - "JA, SCHATZ ?", - "ES REICHT NICHT", - "DER KLAVIERSPIELER IST NICHT DA", - "EIN TRANSSYLVANISCHER GIN-TONIC", - "ICH HABE IMMER NOCH KEIN ZIMMER", - "ES SCHEINT DASS ER IN DER BADEWANNE HaeNGENGEBLIEBEN IST UND DANN EINE KNEIPE AUFGEMACHT HAT", - "ER IST VOLL WIE EIN RUSSE", - "DIESES HAAR.... TJA,ES ERINNERT MICH AN JEMANDEN", - "ES IST EIN KNoeCHRIGES GERIPPE", - "GUCK MAL ! BRAD PITT!", - "ER SCHLaeFT. ES WaeRE WIRKLICH SCHADE, IHN ZU WECKEN", - "ER IST HaeSSLICHER ALS DIDI HALLERVORDEN", - "EIN SARG AUS FICHTENHOLZ", - "ER WIRD MICH IN LECKERE KLEINE SCHEIBCHEN SCHNEIDEN", - "ICH STEH NICHT SO AUF PENDEL. ICH FIND OHRFEIGEN BESSER", - "ICH KANN NICHT. ICH HAB HANDSCHELLEN AN", - "DAS SIEHT DOCH JEDER, DASS DAS EINE GEHEIMTueR IST", - "SIE IGNORIEREN MICH", - "ACH KOMM !", - "LAUT DREHBUCH BEWEGE ich mich, ABER das Spiel war so teuer, dass nichts mehr FueR EIN FITNESS-STUDIO ueBRIG war, also habe ich auch keinen strammen arsch.", - "SCHEINT SO, ALS OB ER EIN BISSCHEN LOSE AN DER WAND HaeNGT", - "ICH GLAUBE KAUM, DASS SIE MIR NueTZEN WIRD. SIE IST VIEL ZU FEUCHT, UM SIE ANZUZueNDEN", - "ZUM WESTFLueGEL ?ICH BIN DOCH NICHT BLoeD !WER WEISS WAS MICH DA ERWARTET !", - "MIT HueBSCHEN TRANSSYLVANISCHEN MOTIVEN", - "", - "WIE SCHADE, DASS DAS DA KEIN LECKERER LAMMBRATEN DRIN IST.", - "ALS ICH BEIM LETZTEN MAL IN EINEN OFEN GEGUCKT HABE, IST DAS HAUS IN DIE LUFT GEFLOGEN", - "DAS IST DAS WAPPEN DER TRANSSYLVANISCHEN FUSSBALLMANNSCHAFT", - "UND WOZU? SOLL ICH MIR DAS ANS KNIE BINDEN ?", - "DIESE SORTE SCHUBLADE LaeSST SICH NICHT oeFFNEN", - "ICH MoeCHTE ECHT NICHT WISSEN, WAS ES DA DRIN ZU ESSEN GIBT!", - "DAS WIRKT ZIEMLICH IMPRESSIONISTISCH AUF MICH", - "DIE NACHT VERSCHLUCKT ALLES... WIE UNHEIMLICH, WAS?", - "SIE KLEMMT", - "DER KoeNIG HAST DU DIR DAS NICHT DENKEN KoeNNEN?", - "NEIN, ICH HAB SCHON EINEN ZU HAUSE, DEN ICH FueTTERE UND SO", - "EIN REGAL MIT BueCHERN UND ANDEREN SACHEN", - "UND WEN SOLL ICH UM DIESE UHRZEIT NOCH ANRUFEN?", - "\"EINKOMMENSERKLaeRUNG LEICHT GEMACHT\" WIE INTERESSANT!", - "ICH HAB SCHON EINS ZU HAUSE.ICH GLAUBE DAS IST WELTWEIT EIN BESTSELLER", - "EIN TOTAL NORMALER SCHLueSSEL", - "ICH GLAUBE, DER GEHoeRT HIER NICHT HIN", - "HEY, DIE FRITTEN SEHEN AUS WIE ECKZaeHNE! ICH BIN HIN UND WEG", - "das ist wohl echt nicht DER moment, RUMZUNASCHEN, WENN MEINE FREUNDIN IN DEN KLAUEN DER fiesesten ausgeburt der Welt ist.", - "WAS FueR EINE RIESENGAUDI DAS MACHT, DAMIT VAMPIRE FERTIGZUMACHEN!", - "MAL GUCKEN, OB NOCH EINER AUFTAUCHT", - "NEIN, ES MUSS MIT NOCH SO EINEM DRECKIGEN, STINKENDEN UND NERVIGEN VAMPIR WIE VORHIN SEIN", - "DAS IST DIE ORIGINALPERueCKE VON ELIVS ALS ER SCHON EINE GLATZE HATTE", - "MEHL, ABER ICH KANN JETZT KEINE MARKEN NENNEN", - "VIELLEICHT EIN ANDERES MAL, OK?", - "EINE WUNDERSCHoeNE AXT. ZU SCHADE, DASS GERADE KEIN VAMPIRKOPF IN DER NaeHE IST", - "NEIN, IM GRUNDE BIN ICH EIN NETTER MENSCH", - "DAS IST DAS DEO VON MAGGIE THATCHER, HIHIHI!", - "EIN ZIEMLICH HueBSCHER UMHANG", - "", - "WIE JEDER BELIEBIGE AST EINES BELIEBIGEN BAUMES AN JEDEM BELIEBIGEN ORT IN DER WELT, NICHTS BESONDERES ALSO", - "\"UNGLAUBLICH\" EIN SEIL IN EINEM VIDEOSPIEL!", - "WOZU DAS WOHL NOCH GUT SEIN WIRD...", - "EIN SEIL AN EINEM AST ODER EIN AST AN EINEM SEIL, JE NACHDEM WIE MAN DAS SO BETRACHTET", - "ES SCHEINT, DAS DIESE ELSTER WAS ueBLES IM SCHILDE FueHRT", - "ZISCH AB, ICH SAG IHR NICHTS, MAL SEHEN OB SIE AUSFLIPPT", - "SIEHT SO AUS ALS WaeRE SIE TOT, ABER STIMMT NICHT,NE?", - "FueR DIESES SPIEL WURDEN KEINE TIERE MISSHANDELT ODER GEToeTET", -}, -{ - "", - "C'EST LA DEUXI\212ME PORTE PLUS GRANDE QUE J'AI VUE DANS MA VIE.", - "ENFIN, PAS AUTANT QUE \207A.", - "ELLE EST BOUCH\202E AVEC DES GROSSES PLANCHES. L'\202GLISE EST PEUT-\210TRE ABANDONN\202E DEPUIS QUELQUES ANN\202ES.", - "MAIS JE NE L'AI PAS OUVERTE.", - "QU'EST-CE QUE JE FAIS? JE L'ARRACHE?", - "BONJOUR, PORTE. JE VAIS T'ENCADRER.", - "C'EST TROP POUR MOI.", - "UNE FEN\210TRE BOUCH\202E AUX GROSSES PLANCHES.", - "JE N'ARRIVE PAS.", - "\200A Y EST.", - "ET POURQUOI?", - "SALUT, FEN\210TRE! AS-TU QUELQUE CHOSE \205 FAIRE CE SOIR?", - "PAS SANS LE PERMIS DE TRAVAUX PUBLIQUES.", - "H\202! CETTE FEN\210TRE A SEULEMENT UNE GROSSE PLANCHE...", - "OH\202! OH\202!-FEN\210TRE!", - "BONJOUR, TOI.", - "", - "JE N'ARRIVE PAS.", - "C'EST BIEN O\227 ELLE EST.", - "", - "C'EST UNE TOMBE EN FORME DE CROIX.", - "NON, MERCI.", - "BONJOUR, LE D\202FUNT: VEUX-TU DES VERMISSEAUX?", - "MAIS OUI. COMME EN POLTERGUEIST.", - "", - "", - "JE REVIENS EN QUINZE MINUTES.", - "D\202FENSE D'AFFICHER.", - "", - "C'EST FERM\202 \205 CL\202.", - "J'EN AI D\202J\205 UN.", - "", - "IL NE R\202POND PAS.", - "MAIS NON, C'EST BIEN GAR\202.", - "C'EST UNE PORTE.", - "UN TIROIR DE LA TABLE.", - "UNE ARMOIRE SUSPECTE.", - "BONJOUR, L'ARMOIRE. \200A VA?", - "", - "", - "C'EST UN CAND\202LABRE TR\212S VIEUX.", - "IL DOIT \210TRE L\205 D\212S QUE MAZINGUER-Z \202TAIT UNE VIS.", - "NON, C'EST UNE RELIQUE.", - "C'EST UN JOLI R\202TABLE.", - "", - "HI! HI! HI!", - "", - "NON.", - "", - "HA! HA! HA! -QUE C'EST BON!", - "", - "", - "", - "JE NE VOIS RIEN DE SP\202CIAL.", - "C'EST FERNAN, LA PLANTE.", - "C'EST UNE DES PIQUES DE LA GRILLE.", - "H\202! L\205-DESSOUS IL Y A UNE BO\214TE D'ALLUMETTES.", - "REGARDE! UN PAQUET DE CLINEX. -ET IL Y A UN TOUT NEUF!", - "IL N'Y A RIEN DE PLUS DANS LE SEAU.", - "C'EST UN AVEUGLE QUI VE VOIT PAS.", - "", - "", - "", - "", - "C'EST UNE GROSSE SOMME D'ARGENT.", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "ELLE N'A RIEN DE SP\220CIAL", - "CELA N'A RIEN D'EXTRAORDINAIRE", - "QU'EST-CE QU'IL Y A?", - "BONJOUR!", - "RIEN DE NOUVEAU?", - "LA FAMILLE, \200A VA?", - "-QUELLES CHOSES TU AS!", - "MAIS, COMME JE VAIS PRENDRE CELA!", - "MA RELIGION ME L'INTERDIT", - "CE N'EST PAS MIEUX", - "BIEN S\352R, MON VIEUX!", - "ON NE PARLE PLUS DE CELA", - "IMPOSSIBLE", - "CELA NE S'OUVRE PAS", - "JE NE PEUX PAS TOUT SEUL", - "SI JE VOULAIS, J' ARRIVERAIS, MAIS \200A ME DONNE DE LA PARESSE", - "JE N'Y VOIT PAS UNE RAISON APPARENTE", - "C'EST UN CERVEAU ASSEZ BIEN", - "ET BIEN CERVEAU, QUE PENSES-TU FAIRE CE SOIR?", - "NON, ON DOIT LE GARDER DANS UN ENDROIT \267 L'ABRI DES MUTATIONS DE L'ATMOSPH\324RE", - "C'EST UN DUR, COMME MON CHEF", - "C'EST UN PIEU TR\324S AIGUIS\220", - "FID\324LE PIEU POINTUUU, NOBLE CH\322NE TRANSYLVAAAN", - "TIENS! JE DOIS COUPER MES ONGLES!", - "B.J. EST L\267-DEDANS. ET QUELLE EST MIGNONE CETTE NANA!", - "ELLE EST FERM\220E TR\324S SOLIDEMENT", - "\"CADENAS SOLIDES S.A.\"", - "C'EST LE TYPIQUE SQUELETTE QU'ON TROUVE DANS LES GE\342LES DE TOUS LES JEUX", - "ON L' EMPLOIE NORMALEMENT POUR INDUIR DU COURANT \220LECTRIQUE AUX APPAREILS QU'Y SONT RACCORD\220S", - "C'EST ABSOLUMENT ARTISANAL, CAR LES JAPONAIS LES FONT MAINTENANT DE POCHE", - "J'AI SEULEMENT VU DANS MA VIE UNE CHOSE SI MOCHE", - "LAISSE. JE NE LUI DIS RIEN POUR S'IL SE F\266CHE", - "IL SEMBLE ASSEZ RATIONNEL", - "C'EST UNE PHOTO DE PLATON EN TRAIN D'\220CRIRE SON DIALOGUE PERDU", - "JE NE SUIS PAS DE CEUX QUI PARLENT AUX POSTERS", - "UN BUREAU ASSEZ MIGNON", - "C'EST UN DIPL\342ME DE CHASSE-CHASSE-VAMPIRES HOMOLOGU\220 PAR L'UNIVERSIT\220 D'OXFORD", - "C'EST UNE NUIT NOIRE AU PLEINE LUNE", - "IL PARA\327T QUE CES VIS NE SONT PAS TR\324S ENFONC\220ES", - "N'Y REGARDES PAS, MAIS JE CROIS QU'UNE CAM\220RA OCCULTE ME VISE", - "UN D\220TECTEUR DE PIEUX ASSEZ MODERNE", - "NON, LE LABORATOIRE EST AU DEUXI\324ME \220TAGE", - "UNE JOLIE TABLE DE NUIT", - "C'EST UN TAS D'ARGENT QUI NE PEUT PAS MANQUER DANS UNE AVENTURE DIGNE DE TEL NOM", - "SI J'\220TAIS RICHE. DUBIDOUDUBIDOUDUBIDOUDUBIDOU", - "CE SONT DES FEUILLES BIZARRES. ON A D\352 LES AMENER DE L'AM\220RIQUE DU SUD OU PAR L\267", - "JE NE PENSE PAS QU'ILS VONT ME R\220PONDRE", - "C'EST UN JOLI CRUCIFIX EN BOIS. L'IC\342NE N'ARRIVE PAS \267 SAISIR TOUT LA SPLENDEUR DE SA BEAUT\220", - "JE PRIE SEULEMENT AVANT DE ME COUCHER", - "H\220!, IL PARA\327T QUE CETTE PIQUE S'EST UN PETIT PEU D\220CROCH\220E", - "TU NE POURRAS TE PLAIGNER APR\324S DU PEU DE PISTES QUE JE TE DONNE", - "C'EST UNE PIQUE ASSEZ CONVENTIONNELLE", - "ILS SONT MIGNONS, MAIS UN PEU SALES", - "NON, NON, ILS NE ME \220COUTERAIENT PAS. HI, HI, HI -QUE C'EST BON!", - "\"LA BELLE DORMANTE DU BOIS\" DE TCHA\330KOVSKI, OU TCHA\330FROSKI, OU N'IMPORTE COMMENT DIT-ON ", - "TR\324S APP\220TISSANT", - "JE NE SUIS PAS DE CEUX QUI SUCCENT DES CHEWING-GUMS D\220J\267 M\266CH\220S", - "UNE FAUCILLE TR\324S MIGNONE. jE ME DEMANDE O\353 SERA LE MARTEAU?", - "\"LES FABRICANTS DE TABAC AVERTISSENT QUE LES AUTORIT\220S SANITAIRES SONT S\220RIEUSEMENT NUISIBLES POUR LA SANT\220 \"", - "UNE BOUGIE COURANTE ET NORMALE ET AVEC DE LA CIRE M\322ME", - "IL FAUT VOIR COMME ELLES LUISENT CES DEUX RUTILANTES MONNAIES!", - "IL FAUT VOIR COMME ELLE LUIT CETTE RUTILANTE MONNAIE!", - "AVEC \200A JE SERAI IMMUNIS\220 CONTRE LES MORSURES DES VAMPIRES", - "NON, CE N'EST PAS ENCORE LE MOMENT", - "IL Y A UN BILLET DE MILLE ET DEUX SOUS", - "ON DIT\"VOUS \322TES PRI\220S DE NE PAS DONNER \267 MANGER AU PIANISTE\"", - "L'OMELETTE, 200. DES PETITS POISSONS FRITS, 150, DES POMMES A\330OLI, 225", - "LES MEILLEURES HAMBURGERS DE CE C\342T\220 DU DANUBE, SEULEMENT 325", - "C'EST UNE JOLIE T\322TE DE MORT AU REGARD TR\324S PER\200ANT -HI, HI, HI, QUE C'EST BON!", - "BONJOUR T\322TE DE MORT, TU ME RAPPELLES L'ONCLE HAMLET", - "J'AI LA HABITUDE DE NE PAS TOUCHER AUX CHOSES QUI ONT V\220CU AUTREFOIS", - "C'EST UNE POUBELLE", - "C'EST UNE MASSUE POUR LE MATCH DE CE SOIR", - "JE ME DEMANDE CE QU'IL AURA DERRI\324RE", - "H\220, CE RIDEAU NE BOUGE PAS!", - "TIENS, QUEL CH\266TEAU SI SOMBRE, H\220? ", - "JE NE PEUX PAS, IL EST TROP LOIN POUR M'ENTENDRE", - "C'EST UNE TYPIQUE FOR\322T TRANSYLVANE, AVEC DES ARBRES", - "MAIS TU NE DIS QUE DES B\322TISES, C'EST UN LIEU OBSCUR!", - "CONFISERIE GARCIA, G\266TEAUX ET CHEWING-GUMS.", - "UNE PORTE TR\324S JOLIE", - "ELLE EST FERM\220E", - "UN TONNEAU COMPL\324TEMENT FERM\220", - "", - "QUELLES BESTIOLES SI MIGNONES!", - "BSSST, BSSST, PETIT CHAT...", - "IL NE R\220POND PAS", - "LA LUNE EST UN SATELLITE TOURNANT AUTOUR DE LA TERRE AVEC UNE P\220RIODE DE ROTATION DE 28 JOURS", - "SALUT, LUNE!, LUN\220E ET \220TOURDIE ", - "ELLE EST COMPL\324TEMENT BOUCH\220E AVEC DES GROSSES PLANCHES", - "C'EST IMPOSSIBLE, CECI NE L'OUVRE PAS NI LE MAJORDOME DE LA T\220L\220", - "H\220, IL PARA\327T QUE L'OMBRE DE CE CYPR\324S-LA EST ALLONG\220E", - "OH\220! H\342TELIEEER!", - "JE VOUDRAIS UNE CHAMBRE", - "SAVEZ-VOUS O\353 EST QUE JE PEUX TROUVER UN TEL COMTE DRASCULA?", - "OUI, QU'EST-CE QU'IL Y A? ", - "ET \200A?", - "EN... EN V\220RIT\220?", - "UNE BONNE QUESTION, JE VAIS VOUS RACONTER MON HISTOIRE, TIENS...", - "JE N'AI QUE POUR CINQ MINUTES", - "JE M'APPELLE JOHN HACKER ET SUIS LE REPR\220SENTANT D'UNE INMOBILI\324RE BRITANNIQUE", - "IL PARA\327T QUE LE COMTE DRASCULA VEUT ACHETER DES TERRAINS \267 GIBRALTAR ET ON M'A ENVOY\220 POUR N\220GOCIER L'AFFAIRE", - "MAIS JE PENSE QUE DEMAIN DE BONNE HEURE JE RETOURNE AVEC MA MAMAN", - "UNE BELLE NUIT, N'EST-CE PAS?", - "NON, RIEN", - "OH\220! PIANISTE!", - "UNE BELLE NUIT", - "ET EN PLUS, IL NE FAIT PAS FROID", - "EH BIEN, RIEN. CONTINUE \267 JOUER", - "C'EST \200A", - "BONJOUR CHEF, \200A VA?", - "ET LA FAMILLE?", - "IL Y A DE L'AMBIANCE ICI, H\220?", - "TANT MIEUX SI JE NE DIS RIEN", - "ON EST MIEUX CHEZ-SOI QU'AILLEURS... ON EST MIEUX DANS... H\220? MAIS VOUS N'\322TES PAS TANTE EMMA. MIEUX ENCORE. -SI JE N'AI PAS AUCUNE TANTE EMMA!", - "OUI, LE MIEN AUSSI. VOUS POUVEZ M'APPELLER COMME VOUS VOULEZ, MAIS SI VOUS M'APPELLEZ JOHNY, JE VIENS COMME LES CHIENS", - "OUI, QUELS COUPS QUE J'AI, N'EST-CE PAS? EN FAIT, O\353 SUIS-JE?", - "OUI", - "A\330E!, A\330E!...", - "OH, OUI! BIEN S\352R", - "EH BIEN! MERCI BEAUCOUP POUR TON AIDE. JE NE TE D\220RANGE PLUS SI TU ME DIS O\353 SE TROUVE LA PORTE, S'IL TE PLA\327T...", - "CAR LE COUP A D\352 ME TOUCHER LA CERVELLE ET JE N'Y VOIS GOUTTE", - "BAH!, \200A FAIT RIEN. J'AI TOUJOURS UNE DE R\220CHANGE", - "OUAH, QUELLE BELLE FEMME! -JE NE M'AVAIS PAS RENDU COMPTE! BIEN S\352R, SANS LES LUNETTES...", - "\220COUTE...", - "ET \200AAAAAA?!", - "NE T'EN FAIS PAS B. J., MON AMOUR! JE VAIS TE SAUVER DES GRIFFES DE CELUI-L\267 ", - "IL ME CASSE LE NEZ, TIENS!", - "AHHH, UN HOMME-LOUP! MEURS MAUDIT!", - "OUI, C'EST CELA...", - "OUI, C'EST CELA... JE CROIS QUE JE VAIS SUIVRE MON CHEMIN. PARDON.. ", - "QUOI?", - "EH BIEN, EN V\220RIT\220, BIEN PENS\220... JE NE CROIS PAS", - "DIS -MOI, OH! \220RUDITE PHILOSOPHE! Y A-T-IL UNE R\220LATION CAUSE-EFFET ENTRE LA VITESSE ET LE LARD?", - "\200A VA, \200A VA, ABANDONNE. EN TOUT CAS, JE NE SAIS PAS POURQUOI JE L'AI DIT.", - "QU'EST-CE QUE TU FAIS ICI EN TRAIN DE PHILOSOPHER AU LIEU DE MANGER DU MONDE?", - "QU'EST-CE QUE C'EST QUE \200A?", - "\220COUTE, PEX-TU R\220P\220TER CETTE PHRASE DES \"INCLINATIONS PR\220-\220VOLUTIVES\"?", - "BIEN S\352R, MON VIEUX. CETTE HISTOITE QUE TU M'AS LACH\220E AVANT. CE QUE JE N'AI PAS BIEN COMPRIS...", - "NON, LE MIEUX SERA DE NE RIEN DIRE. CAR SI JE LE TOUCHE LA VEINE.....", - "OUI, QUE SE PASSE-T-IL?", - "OUI, QU'EST-CE QU'IL Y A? ", - "EH BIEN, MAINTENANT QU'IL ABORDE LE SUJET JE LUI DIRAI QUE...", - "", - "EN FAIT, QU'ARRIVERAIT-IL SI UN VAMPIRE SE POURVOYAIT DE LA FORMULE PAR HASARD... ", - "EH BIEN, RIEN. \220COUTE, CECI NE TE SEMBLE PAS UN RAVAUDAGE QU'ON A MIS EN SC\324NE POUR EN FINIR T\342T AVEC LE JEU? BON, PEUT-\322TRE PAS", - "C'EST VIDE!", - "POURQUOI TU M'AS VOL\220 MON AMOUR. B.J. SI ELLE N'EST PAS L\267, LA VIE N'AS PAS DE SENS POUR MOI", - "SON CERVEAU?!", - "CE N'EST POUR RIEN, MAIS JE CROIS QUE TON PETIT MONSTRE M'A F\266CH\220", - "MA VIERGE, QUE JE RESTE TEL QUE JE SUIS!", - "TU N'AURAS PAS LE DERNIER MOT. C'EST S\352R QUE MAINTENANT APPARA\327T SUPER-LOPEZ ET ME LIB\324RE!", - "QUELLE MERDE DE JEU DONT MEURT LE PROTAGONISTE!", - "UN INSTANT, QU'Y A-T-IL DE MON DERNIER D\220SIR?", - "HA! HA! MAINTENANT JE SUIS IMMUNIS\220 CONTRE TOI, D\220MON MAUDIT. CETTE CIGARETTE EST UNE POTION ANTI-VAMPIRES QUI M'A DONN\220 VON BRAUN ", - "OUI, C'EST S\352R, MAIS TU N'OBTIENDRAS JAMAIS DE MOI LA FORMULE", - "JE PEUX SUPPORTER LA TORTURE, ET ENCORE LA CR\220ER ", - "NON, S'IL VOUS PLA\327T, JE PARLERAI, MAIS NE ME FAITES PAS \200A!", - "EH BIEN. JE T'AI D\220J\267 DIT CE QUE TU VOULAIS SAVOIR. MAINTENANT D\220LIVRE-NOUS, B.J. ET MOI, ET FICHEZ-NOUS LA PAIX", - "B.J.! QU'EST-CE QUE TU FAIS L\267? DRASCULA, O\353 EST-IL?", - "QU'IL EST M\220CHANT! C'EST SEULEMENT PAR-CE QU'IL APPARTIENT \267 LA NOBLESSE QU'IL CROIT POUVOIR EXERCER LE DROIT DE GAMBADE AVEC N'IMPORTE QUI", - "\267 BAS L'ARISTOCRATIE ARBITRAIRE!", - "DEBOUT LES PAUVRES DU MOOONDE....!", - "ET D'APR\324S CE QUE JE VOIS ON T'A ENCHA\327N\220 AVEC CADENAS ET TOUT", - "BON, \200A VA. N'AURAS-TU PAS UNE \220PINGLE?", - "BON, BON, NE T'EN FAIS PAS COMME \200A. JE PENSERAI \267 QUELQUE CHOSE.", - "H\220! TAVERNIER!", - "COMMENT VA LE MATCH?", - "QUI EST-CE?", - "NE VOIS-TU PAS QUE DRASCULA EST ICI?", - "ALORS, ON VA FINIR AVEC LUI, NON?", - "SERS -MOI UN COUP...", - "RIEN. J'AI OUBLI\220 CE QUE J'ALLAIS TE DIRE", - "OU\207BIEN\207TU\207ME\207SERS\207UN\207COUP\207OU\207JE\207ME\207METS\207\267\207JOUER\207DU\207PIANO", - "COMBIEN IL RESTE POUR QUE LE MATCH FINISSE?", - "BON SOIR", - "COMME VAS-TU, IGOR? BOSSU? -HI! HI! HI! QUE C'EST BON! ", - "QU'EST-CE QU'ON SUPPOSE QUE TU FAIS?", - "EH BIEN, NON!", - "ALORS, METS-TOI DES LUNETTES", - "QU'EST QUE C'EST QU'UNE ORGIE SURNATURELLE?", - "\200A VA, \200A VA, ARR\322TE-TOI. JE ME FAIS D\220J\267 UNE ID\220E", - "NE POURRAIS-TU PAS ME DIRE O\353 SE TROUVE DRASCULA? ", - "ALLONS, S'IL TE PLA\327T", - "POURQUOI PAS?", - "AH! MAIS IL DORME PENDANT LA NUIT?", - "EH BIEN! QUE LA RENTE SE DONNE BIEN", - "CE QUE JE DOIS LUI PARLER", - "OH\220! SQUELEEETTE! ", - "SAPRISTI! -UN SQUELETTE QUI PARLE!", - "RACONTE-MOI, COMMENT EST-TU VENU JUSQU'ICI?", - "ET POUR QUELLE RAISON VOUDRAIT DRASCULA CR\220ER UN MONSTRE? ", - "COMMENT T'APPELLES-TU, AMI SQUELETTE?", - "\220COUTE, VEUX-TU QUE JE T'APPORTE QUELQUE CHOSE \267 MANGER?", - "TU DOIS AVOIR L'ESTOMAC VIDE. -HI! HI! HI!", - "VRAIMENT JE N'AI PAS ENVIE DE PARLER MAINTENANT", - "MON DIEU! (SIFFLEMENT) J'ESP\324RE QUE...(SIFFLEMENT) ET QUE...(SIFFLEMENT) DEUX FOIS!", - "J'AI L'AIM\220E VRAIMENT. \200A VA, JE SUIS D'ACCORD, IL N'\220TAIT PAS UN G\220NIE, MAIS PERSONNE EST PARFAIT, N'EST-CE PAS? ", - "DE PLUS, ELLE AVAIT UNE FIGURE \220POUSTOUFLANTE ", - "JE NE SERAI PLUS LE M\322ME. JE VAIS M'ENFERMER DANS UN MONAST\324RE POUR VOIR FUIR MA VIE LENTEMENT", - "RIEN NE POURRA M'EN SORTIR D\220J\267 DE CETTE MIS\324RE PARCE QUE...", - "DE QUI? DE QUI?", - "JE VEUX \322TRE UN PIRATE", - "JE VEUX \322TRE PROGRAMMEUR", - "RACONTEZ-MOI QUELQUE CHOSE SUR PELAYO", - "JE CONTINUERAI \267 JOUER ET J'OUBLIERAI QUE VOUS AI VU ", - "QUI AURA PENS\220 \267 CETTE B\322TISE?", - "C'EST UN SAC COMME CELUI DE MA GRANDE-M\324RE", - "MAIS QUE JE SUIS BEAU!", - "PLUS JE ME REGARDE PLUS JE ME PLAIS", - "ET APR\324S COMMENT JE ME FERME?", - "IL FAUDRA QUE M'OUVRE D'ABORD, NON?", - "JE SUIS BIEN O\353 JE SUIS", - "JE M'AI D\220J\267", - "SALUT, MOI!", - "JE VAIS ME LES METTRE \267 TEMPS", - "JE NE VOIS RIEN DE SP\220CIAL", - "C'EST BIEN O\353 IL EST", - "ET POURQUOI FAIRE?", - "JE NE PEUX PAS", - "SALUT, TOI!", - "C'EST LE PANTH\220ON DE L'ONCLE D\220SIR\220", - "OH\220! ONCLE D\220SIR\220\220\220\220!", - "NON, JE NE VEUX PAS ME COUPER ENCORE UNE FOIS", - "HEM! HEM!...!", - "YAMM, HEMMM, JH!", - "OUI, COF,COF!", - "TIENS, IL Y A ICI UN CHEWING-GUM COLL\220", - "C'EST LE MOVILANI, LE CADEAU QUI M'ONT DONN\220 POUR NO\323L", - "QUE C'EST HAUT!", - "SORS DANS LE BALCON JULIETTE!", - "TU EST LA LUMI\324RE QUI \220CLAIRE MON CHEMIN!", - "H\220, PORTE! QU'EST-CE QU'IL Y A?", - "OH\220! MACHINE \267 TABAC DE TRANSYLVANIIIE", - "C'EST UNE MACHINE \267 D\220BIT DE TABAC", - "J'AI UNE AUTRE MONNAIE L\267 -DEDANS", - "NON, J'AI D\220CID\220 ABANDONNER LE TABAC ET L'ALCOOL", - "D\324S MAINTENANT JE VAIS ME CONSACRER SEULEMENT AUX FEMMES", - "C'EST UN VOL! RIEN EST SORTI!", - "ENFIN! ", - "C'EST \200A, UN BAHUT", - "SALUT, BAHUT! TU T'APPELLES COMME MON COUSIN, QUI S'APPELLE RAUL", - "J'AI TROUV\220 LE SAC DE B.J..", - "MON DIEU! JE N'Y ME VOIS PAS -SUIS UN VAMPIRE!", - "...AH, NON! CE N'EST QU'UN DESSIN!", - "PETIT MIROIR: \"C'EST QUI LE PLUS BEAU DU ROYAUME?\"", - "IL NE VEUT PAS M'OUVRIR", - "TR\324S BIEN. J'AI MIS LES TAMPONS", - "C'EST UN DIPL\342ME DE CHASSE-VAMPIRES HOMOLOGU\220 PAR L'UNIVERSIT\220 DE CAMBRIDGE", - "NON, IL ME FAUT ENCORE D'INGR\220DIENTS, PAS LA PEINE DE LUI REVEILLER", - "C'EST QUE JE SUIS FAUCH\220", - "C'EST UNE LAMPE BRITANNIQUE", - "TAVERNIER! -AIDEZ-MOI!", - "UN VAMPIRE EST APPARU ET IL A ENLEV\220 MA FIANC\220E", - "MAIS, N'ALLEZ VOUS PAS M'AIDER?!", - "MORTE? QUE VOULEZ-VOUS DIRE?", - "HEM!", - "UN VAMPIRE A S\220QUESTR\220E LA FILLE DE LA 506!", - "IL FAUT QUE TU M'AIDES!", - "TU NE SAIS PAS JOUER AUCUNE PI\324CE DES INHUMAINS?", - "COMMENT TU TE SUPPORTES TOUT LE JOUR EN JOUANT LA M\322ME CHOSE?", - "ET ALORS, POURQUOI TU M'\220COUTES?", - "PR\322TE-MOI LES TAMPONS", - "ALLONS! JE VAIS TE LES REDONNER TOUT DE SUITE", - "ALLOOONSSS..." - "AU REVOIR. JE DOIS TUER UN VAMPIRE", - "", - "EN QUOI TU PARLES! EN TRANSYLVAN?", - "C'EST QUI L'ONCLE D\220SIR\220?", - "MAIS QU'EST-CE QU'IL Y A AVEC CE DRASCULA-L\267?", - "QUI EST-CE CE VON BRAUN-L\267?", - "ET POURQUOI IL NE LE FAIT PAS?", - "ET O\353 PEUX-JE TROUVER VON BRAUN?", - "EH BIEN, MERCI ET AU REVOIR. QUE TU LA DORMES BIEN", - "IL VAUDRA MIEUX SONNER D'ABORD", - "LE PROFESSEUR VON BRAUN, C'EST VOUS?", - "ET NE POUVEZ-VOUS PAS M'INDIQUER O\353 JE PEUX...?", - "JE NE CROIS PAS QU'IL SOIT LE NAIN GANYM\324DE", - "PROFESSEUR!", - "AIDEZ-MOI! -LA VIE DE MA BIEN AIM\220E DEPENDE DE VOUS!", - "\200A VA, JE N'AI PAS BESOIN DE VOTRE AIDE", - "D'ACCORD. JE M'EN VAIS", - "N'AIES PAS PEUR. NOUS ALLONS VAINCRE DRASCULA ENSEMBLE", - "ALORS, POURQUOI NE M'AIDEZ VOUS PAS?", - "JE LES AI", - "OUI, JE LES AI!", - "D'ACCORD", - "...ER ...OUI", - "JE VIENS POUR RENTRER DANS CETTE CABINE", - "SUIS PR\322T \267 CONFRONTER VOTRE \220PREUVE", - "\200A VA, VIEUX RIDICULE. JE SUIS VENU CHERCHER MON ARGENT", - "NON, RIEN. JE M'EN ALLAIS D\220J\267", - "PARDONNE-MOI", - "CE LIVRE T'INT\220RESSE? AVEZ-VOUS DES PARTITIONS DE TCHA\330KOVSKY?", - "COMMENT PEUX-JE TUER UN VAMPIRE?", - "ON NE T'A JAMAIS DIT QUE C'EST MAUVAIS DORMIR DANS UNE MAUVAISE POSTURE?", - "EH BIEN, C'EST \200A QUE MA M\324RE ME DIT TOUJOURS", - "POURQUOI DRASCULA N'A PU JAMAIS TE TUER?", - "ET QU'EST-CE QUE S'EST PASS\220?", - "C'EST SUPER! -AVEZ-VOUS UNE POTION D'IMMUNIT...!", - "ALORS?", - "TR\324S BIEN", - "POUVEZ-VOUS ME R\220P\220TER CE DONT J'AI BESOIN POUR CETTE POTION?", - "EH BIEN! JE PARS RAPIDE LE CHERCHER", - "\220COUTEZ, QU'EST-CE QUE C'EST PASSE\220 AVEC LE PIANISTE?", - "J'AI\207D\220J\267\207TOUS\207LES\207INGR\220DIENTS\207DE\207CETTE\207POTION", - "UNE QUESTION: QU'EST.CE QUE C'EST CELA D' ALUCSARD ETEREUM?", - "PARLEZ, PARLEZ... ", - "ET C'EST O\353 CETTE GROTTE?", - "QU'EST-CE QU'IL Y A? N'AVIEZ VOUS PAS UN TRIBUNAL?", - "...MAIS ...ET SI JE TROUVE ENCORE DES VAMPIRES?", - "C'EST UN VAMPIRE QUI M'EMP\322CHE L'ENTR\220E", - "IL RESSEMBLE \267 YODA, MAIS C'EST UN PEU PLUS GRAND", - "H\220, YODA! SI TU ME LAISSES PASSER JE TE DONNE UNE MONNAIE", - "BON, \200A VA. ON NE PEUT RIEN TE DIRE", - "H\220, VAMPIRE! BELLE NUIT, N'EST-CE PAS?", - "ON T'A D\220J\267 DIT QUE TU RESSEMBLES \267 YODA?", - "ES-TU UN VAMPIRE OU UNE PEINTURE \267 L'HUILE?", - "IL VAUX MIEUX NE RIEN TE DIRE, POUR SI TU TE F\266CHES", - "C'EST FERM\220E \267 CL\220", - "LA PIE POURRAIT M'ARRACHER UN OEIL SI J'EN ESSAIE!", - "C'EST FERM\220E! -MON DIEU, QUELLE PEUR!", - "LES GONDS SONT OXYD\220S", - "L\267-DEDANS IL Y A SEULEMENT UN POT AVEC DE LA FARINE", - "CECI A ENLEV\220 L'OXYDE", - "J'AI TROUV\220 UN PIEU DE PIN", - "JE PRENDRAI CELUI-CI QUI EST PLUS GROS", - "BON, JE CROIS QUE JE PEUX ME D\220BARRASSER MAINTENANT DE CE STUPIDE D\220GUISSEMENT", - "LE PASSAGE AUX DONJONS EST FERM\220 \267 CAUSE DES TRAVAUX. VOUS \322TES PRI\220S D'UTILISER L'ENTR\220E PRINCIPALE. EXCUSEZ LES ENNUIES", - "...IL EST P\266LE. AVEC DE GROSSES DENTS. IL A UN TOUPET ET UTILISE UNE CAPE... -C'EST S\352REMENT DRASCULA!", - "C'EST B.J.! B.J. TU EST BIEN?", - "OUI, JE SAIS QU'ELLE EST B\322TE, MAIS JE SUIS SEUL", - "N'AURAS-TU PAS UNE CL\220 PAR L\267, N'EST-CE PAS?", - "N'AURAS-TU PAS UN ROSSIGNOL, PAR HASARD?", - "DONNE-MOI UNE \220PINGLE. JE VAIS FAIRE COMME MCGYVER", - "NE BOUGES PAS, JE REVIENS TOUT DE SUITE", - "ZUT! -S'EST CASS\220E!", - "OL\220\220\220! ET EN PLUS JE ME SUIS RAS\220, COLL\324GUE!", - "OUI, MON AMOUR?", - "IL N'ARRIVE PAS", - "LE PIANISTE N'EST PAS L\267", - "UN COKTAIL TRANSYLVAN", - "JE N'AI PAS UNE CHAMBRE", - "SELON PARA\327T, IL EST REST\220 COINC\220 DANS LA BAIGNOIRE ET D\220CIDA ALORS D'OUVRIR UN BAR ", - "IL EST SO\352L COME UNE CUVE DE CUBA", - "CE CHEVEU... LE CAS CE QU'IL ME RAPPELLE QUELQU'UN", - "C'EST UN SQUELETTE OSSEUX", - "REGARDE! MIGUEL BOS\220!", - "IL DORME. CE SERAIT DOMMAGE LE R\220VEILLER", - "IL EST PLUS MOCHE QU'\220MILE DE PAZ", - "UN CERCUEIL EN BOIS DE PIN", - "IL VA ME COUPER EN PETITES TRANCHES, COMME UN SAUCISSON", - "JE N'AIME PAS LES PENDULES. JE PR\220F\324RE LES ARTICHAUTS", - "MES MAINS SONT EMMENOTT\220ES. JE N'ARRIVERAI PAS", - "IL SAUTE AUX YEUX QUE C'EST UNE PORTE SECR\324TE", - "ILS M'IGNORENT", - "C'EST BIEN!", - "DANS LE SCRIPT IL BOUGEAIT, MAIS LE JEU A SURPASS\220 LE BUDGET ET ON N'A PAS PU ME PAYER UN GYMNASE POUR ME METTRE EN FORME. DONC, POINT DU TOUT", - "ELLE PARA\327T UN PEU D\220TACH\220E DU MUR", - "JE NE CROIS PAS POUVOIR M'EN SERVIR. ELLE TROP HUMIDE POUR L'ALLUMER", - "\267 L'AILE OUEST? -M\322ME PAS EN FOU ACHEV\220! -VA SAVOIR QU'AURAIT-IL L\267-BASI!", - "IL Y A DE JOLIS MOTIFS TRANSYLVANS", - "", - "QUEL DOMMAGE NE PAS AVOIR TROUV\220 L\267-DEDANS UN PETIT AGNEAU EN TRAIN DE SE R\342TIR!", - "LA DERNI\324RE FOIS QUE J'AI OUVERT UN FOURNEAU LA MAISON A VOL\220 EN \220CLATS", - "C'EST L'ENSEIGNE DE L'\220QUIPE DE FOOT-BALL DE LA TRANSYLVANIE", - "ET POURQUOI FAIRE? POUR ME LA METTRE \267 LA T\322TE?", - "JE NE CROIS PAS QUE CES TIROIRS SOIENT DE CEUX QUI S'OUVRENT", - "JE NE VEUX PAS SAVOIR LA NOURRITURE QU'IL Y AURA L\267-DEDANS!", - "J'AI L'IMPRESSION QUE C'EST DE L'IMPRESSIONNISME", - "LA NUIT S'EMPARE DE NOUS TOUS... QUELLE PEUR, N'EST-CE PAS?", - "ELLE EST BOUCH\220E", - "C'EST LE ROI. NE L'AVAIT-TU PAS IMAGIN\220?", - "NON, J'EN AI D\220J\267 UN CHEZ MOI ET JE LUI DONNE \267 MANGER EN PLUS", - "UN PLACARD AVEC DES LIVRES ET D'AUTRES CHOSES", - "ET QUI J'APPELLE \267 CES HEURES-L\267?", - "\"COMMENT FAIRE LA D\220CLARATION D'IMP\342TS\" COMME C'EST INT\220RESSANT!", - "J'AI D\324J\267 UN CHEZ MOI. JE CROIS QUE C'EST UN BEST-SELLER MONDIAL", - "UNE CL\220 COMPL\324TEMENT NORMALE", - "IL ME SEMBLE QUE CELLE-CI N'EST PAS D'ICI", - "H\220! CE SONT DES FRITES SOUS FORME DE DENT CANINE! \200A ME PLA\327T", - "JE NE CROIS PAS QU'IL SOIT LE MEILLEUR MOMENT POUR MANGER DES GOURMANDISES, AVEC MA FIANC\220E AUX MAINS DE L'\322TRE LE PLUS MAUVAIS QU'UNE M\324RE A PU ACCOUCH\220", - "COMME JE SUIS BIEN EN TUANT DES VAMPIRES AVEC CELA!", - "VOYONS SI APPARA\327T T\342T UN AUTRE", - "NON, IL FAUT QU'IL SOIT AVEC UN SALE ET PUANT VAMPIRE, COMME CELUI QUI J'AI TU\220 AVANT", - "C'EST L'AUTHENTIQUE PERRUQUE QU'ELVIS AVAIT UTILIS\220E QUAND IL EST DEVENU CHAUVE", - "C'EST DE LA FARINE, MAIS JE NE PEUX PAS DIRE DES MARQUES", - "PEUT-\322TRE DANS UN AUTRE MOMENT, D'ACCORD?", - "C'EST UNE HACHE MAGNIFIQUE, DOMMAGE DE NE PAS POUVOIR SE PAYER AUCUNE T\322TE DE VAMPIRE PAR L\267", - "NON. JE SUIS UNE BONNE PERSONNE AU FOND", - "C'EST LE D\220ODORANT DE LA THACHER-HI!HI!HI!", - "C'EST UNE CAPE ASSEZ MIGNONE", - "", - "TOUT COMME LES BRANCHES DE TOUS LES ARBRES DU MONDE, C'EST-\267-DIRE SANS RIEN DE PARTICULIER", - "OH! C'EST INCROYABLE! -UNE CORDE DANS UNE AVENTURE DESSIN\220E!", - "JE ME DEMANDE \267 QUOI SERVIRA-T-ELLE...?", - "UNE CORDE ATTACH\220E \267 UNE BRANCE OU UNE BRANCHE ACROCH\220E \267 UNE CORDE, \200A D\220PEND DU POINT DE VUE", - "IL PARA\327T QUE CETTE PIE \267 DE TR\324S MAUVAISES INTENTIONS", - "TAIS-TOI! JE NE LA DIS RIEN, POUR SI ELLE SE F\266CHE", - "ELLE SEMBLE MORTE, MAIS C'EST UNE MENSONGE", - "IL N'Y A AUCUN ANIMAL ABiM\220 DANS LA PRODUCTION DE CE JEU", -}, -{ - "", - "\220 la seconda porta pi\243 grande che ho vista nella mia vita", - "Forse.., no", - "\202 chiusa con tabelle. La chiesa deve essere abbandonata da tanti anni fa.", - "Ma se non la ho aperta", - "Che faccio? La tolgo?", - "Ciao porta. Vado a farti una cornice", - "Troppo per me", - "una finestra chiusa con tabelle", - "Non ce la faccio", - "Eccolo", - "E per che?", - "Ciao finestra. Hai qualcosa da fare stasera?", - "No senza il permesso del Ministero dei Lavori Pubblici", - "-eh! quella finestra ha soltanto una tabella..", - "-Eooooo! -Finestra!", - "Tu, ciao", - "", - "Non ce la faccio", - "Va bene dov'\202 ", - "", - "\220 una tomba in forma di croce", - "Non grazie", - "Ciao morto. Vuoi delle patatine a forma di vermi?", - "Si. Come in Poltergueist.", - "", - "", - "Torno in quindici minuti", - "Vietato affigere manifesti", - "", - "\220 chiuso con la chiave", - "Ne ho gi\240 uno.", - "", - "Non risponde.", - "No, \202 ben parcheggiato.", - "\220 una porta.", - "Un casseto del tavolino.", - "Un sospettoso armadio.", - "Ciao armadio. Come va?.", - "", - "", - "\220 un candelabro molto vecchio.", - "Deve essere qu\241 da che Mazinguer-Z era una vite.", - "No.\220 una reliquia.", - "\220 una bella pala.", - "", - "Hi, hi, hi", - "", - "No.", - "", - "Ha,ha,ha . - che buono!", - "", - "", - "", - "Non vedo niente di speciale.", - "Ferdinan, la pianta.", - "\220 una degli spunzoni della cancellata.", - "-Eh! Qu\241 sotto c'\202 una scatola di cerini", - "-Guarda! un pacco di fazzoletti. -E c'\202 ne uno senza utilizzare!.", - "Non c'\202 niente di pi\243 nel secchio.", - "\220 un cieco che non vede", - "", - "", - "", - "", - "\220 una abbondante quantit\240 di soldi", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "NON HA NULLA DI SPECIALE", - "NON \324 MICA SPECIALE", - "TU! CHE C'\324 ?", - "CIAO", - "NIENTE NUOVO?", - "-COME VA LA FAMIGLIA?", - "- MA CHE STAI A DIRE?", - "-MA COME VADO A PRENDERE QUELLA COSA!", - "\324 VIETATO DALLA MIA RELIGIONE", - "MEGLIO DI NO", - "-COME NO!", - "NEANCHE PARLARNE", - "IMPOSSIBILE", - "QUESTO NON SI APRE", - "IO SOLO NON CE LA FACCIO", - "SE VORREI POTREI, MA MI FA PIGRIZIA", - "NON TROVO UNA BUONA RAGIONE", - "\324 UN CERVELLO ABBASTANZA CARINO", - "ALLORA, CERVELLO, CHE NE PENSI DI FARE STASERA?", - "NO, DEVE CONSERVARSI IN UN POSTO CHIUSO ALLA AZIONE MUTANTE DELLA ATMOSFERA", - "\324 COS\336 DURO, COME IL MIO CAPO", - "UNA TALEA MOLTO AFFILATA", - "FEDELE TALEA AFFILATAAA, NOBILE ROVERE TRANSILVANOOO", - "-INSOMMA, DEVO TAGLIARMI LE UNGHIE!", - "-LA, DENTRO, C'\324 B.J,E MAMMA MIA, CHE FIGA!", - "\324 CHIUSA SOTTO LUCCHETTO E CATENACCIO", - "\"LUCCHETTO E CATENACCIO S.A\"", - "\324 IL TIPICO SCHELETRO CHE C'\324 IN TUTTE LE CARCERE DI TUTTI I VIDEO-GIOCHI", - "SI UTILIZA PER DARE ELETRICIT\267 AGLI APARATTI COLLEGATI A LUI", - "\324 TOTALMEN11TE ARTIGIANO, PERCHE I GIAPONESSI LI FANNO TASCABILI", - "NELLA MIA VITA, HO VISTO SOLTANTO UNA VOLTA UNA COSA COS\336 BRUTTA", - "SMETILLA. NON DICO NULLA PER SE SI ARRABBIA", - "SEMBRA ABBASTANZA RAZIONALE", - "\324 UNA FOTO DI PLATONE SCRIVENDO IL SUO DISCORSO PERSO", - "NON SONO DI QUELLI CHE PARLANO CON POSTERS", - "UNA SCRIVANIA MOLTO CARINA", - "\324 UN DIPLOMA DI CACCIA-CACCIA-VAMPIRI OMOLOGATO DALLA UNIVERSIT\267 DI OXFORD", - "\324 NOTTE BUIA CON LUNA PIENA", - "SEMBRA CHE QUESTE VITI NON SONO MOLTO AVVITATE", - "NON GUARDARE, MA CREDO CHE UNA TELECAMERA NASCOSTA MI ST\267 REGISTRANDO", - "UN DETETTORE DI TALEE MOLTO MODERNO", - "NO, IL LABORATORIO SI TROVA NEL SECONDO PIANO", - "UN BEL TAVOLINO", - "\324 UN SACCO DI SOLDI CHE NON PUO MANCARE IN UNA AVVENTURA CHE SIA COS\336 IMPORTANTE", - "IF I WERE A RICHMAN, DUBIDUBIDUBIDUBIDUBIDUBIDUBIDU", - "SONO DELLE STRANE FOGLIE. DEVONO AVERLE PORTATE DALLA SUDAMERICA", - "NON CREDO CHE SIA RISPOSTO", - "\324 UN BEL CROCIFISSO DI LEGNO. LA ICONA NON RIFLESSA TUTTA LA SUA BELLEZA", - "IO SOLO PREGO PRIMA DI ANDARMENE AL LETTO", - "-EH, SEMBRA CHE QUESTO SPUNZONE \324 UN PO ALLENTATO!", - "E POI TI LAMENTI PERCHE NON TI DO SUGGERIMENTI", - "\324 UNO SPUNZONI ABBASTANZA CONVENZIONALE", - "SONO CARINI, SEBBENE HANNO PARECHIO POLVERE", - "NO, NON MI SENTIRANO; HI,HI,HI -CHE BUONO!", - "\"LA BELLA ADDORMENTATA DEL BOSCO\" DI CIAIKOSKY, O CIOIFRUSKY, O COME SI DICA", - "MOLTO APPETITOSA", - "NO, IO NON SONO DI QUELLI CHE SI METTONO IN BOCCA GOMME USATE", - "UNA FALCE MOLTO CARINA. MI DOMANDO DOVE CI SAR\265 IL MARTELLO", - "\"I FABBRICANTI DI TABACCO AVVERTONO CHE IL TABACCO NUOCE GRAVEMENTE LA SALUTE\"", - "UNA CANDELA NORMALE, ANZI CON CERA", - "MAMMA MIA COME BRILLANO QUESTE DUE BRILLANTI MONETE", - "MAMMA MIA COME BRILLA QUESTA BRILLANTE MONETA", - "CON QUESTO SAR\220 IMMUNE AI MORSI DEI VAMPIRI", - "NO, ANCORA NON \220 IL MOMENTO", - "C'E UN BIGLIETTO DI DIECIMILA E UN PAIO DI MONETE", - "DICE \"SI PREGA DI NON BUTTARE CIBO AL PIANISTA\"", - "OMELETTA, 3.000 .PESCI FRITI, 2.000,PATATINE, 2.500", - "LE MIGLIORI HAMBURGUER A QUESTA PARTE DEL DANUBIO, SOLTANTO PER 4.000", - "UN BEL TESCHIO, CON UNO SGUARDO MOLTO PENETRANTE. HI,HI,HI, CHE BUONO!", - "CIAO TESCHIO, MI RICORDI AL ZIO DI HAMLET", - "HO L'ABITUDINE DI NON TOCCARE COSE CHE SIANO STATE VIVE", - "UN CESTINO", - "UN TOTOCALCIO PER LA PARTITA DI STASERA", - "MI DOMANDO CHE CI SAR\265 DIETRO", - "-EH, QUESTA TENDE NON SI MUOVE!", - "MADONNA, CHE TETRO \220 QUESTO CASTELLO.", - "NON CE LA FACCIO, \220 TROPPO LONTANO PER SENTIRMI", - "UN TIPICO BOSCO TRANSILVANO, CON GLI ALBERI", - "-MA CHE SCIOCHEZZE DICI, \220 MOLTO BUIO", - "PASTICCERIA ROSSI. DOLCI E GOMME", - "UNA PORTA MOLTO BELLA", - "\220 CHIUSA", - "UN FUSTO COMPLETAMENTE CHIUSO", - "", - "CHE ANIMALETTI COS\326 BELLI!", - "BSSSSSS,BSSSS, GATINO..", - "NON RISPONDE", - "LA LUNA \220 UN SATELLITE CHE GIRA INTORNO LA TERRA CON UN PERIODO DI RIVOLUZIONE DI 28 GIORNI", - "CIAO, LUNA LUNETTA", - "\220 TOTALMENTE CHIUSA CON TABELLE", - "IMPOSSIBILE. QUESTO, NON LO APRE N\220 HOUDINI", - ".EH, SEMBRA CHE L'OMBRA DEL CIPRESSE \220 ALUNGATA", - "-EOOO, BARISTA", - "VORREI UNA CAMERA", - "SA DOVE POSSO TROVARE A UNO CHE SI FA CHIAMARE CONDE DRASCULA", - "SI, PER CHE?", - "COME MAI?", - "DA.....DAVVERO?", - "BUONA DOMANDA, GLI RACONTER\220 LA MIA STORIA, SENTA..", - "SONO SOLTANTO CINQUE MINUTI", - "MI CHIAMO JOHN HACKER, E SONO RAPPRESENTANTE DI UNA IMMOBILIARIE BRITANICA", - "MI HANNO DETTO CHE IL CONDE DRASCULA VUOLE COMPRARE DEI TERRENI A GIBRALTAR, E SONO QU\326 PER NEGOZIARE LA VENDITA", - "MA CREDO IO CHE DOMANI PRESTO TORNO CON LA MAMMA", - "BELLA NOTTE, VERO?", - "NO, NIENTE", - "EOOOO, PIANISTA", - "BELLA NOTTE", - "ANZI, NON FA FREDDO", - "ALLORA... TI LASCIO CONTINUARE A SUONARE", - "VA BENE", - "CIAO CAPO, COME VA?", - "E LA FAMIGLIA?", - "C'\220 GENTE QU\326, EH?", - "MEGLIO NON DICO NULLA", - "SI ST\265 MEGLIO A CASA CHE A NESSUN POSTO... -EH? MA SE LEI NON \220 LA ZIA EMMA. ANZI. SE IO NON HO NESSUNA ZIA EMMA.", - "SI, IL MIO ANCHE. LEI PUO CHIAMARMI COME GLI PARA, MA SE MI CHIAMA JOHNY, VENGO SUBITO COME I CANI", - "SI, CHE SPIRITOSO SONO, VERO? MAA.. DOVE MI TROVO?", - "SI.", - "MANAGIA..", - "OH, SI. COME NO", - "ALLORA GRAZIE MILE PER DARMI IL TUO AIUTO. NON TI DISTURBO PI\351 . SE MI DICI DOV'\220 LA PORTA, PER FAVORE...", - "PERCHE LA BOTTA HA DOVUTO DAGNARMI IL CERVELLO E NON VEDO UNA MADONNA", - "NON FA NIENTE. SEMPRE NE PORTO ALTRI IN PI\351 ", - "-UFFA, CHE FIGA!- NON MI ERA ACCORTO, CERTO, SENZA GLI OCCHIALI", - "SENTI..", - "COME MAI...?!", - "NON TI PREOCUPARE B.J., AMORE MIO! TI LIBERER\220 DA QUEL TIZIO", - "MI HA FATTO ARRABBIARE", - ".AHHH, IL LUPO- MANNARO! -MUORE MALDITO!", - "BENE, CREDO...", - "BENE, CREDO CHE PROSSIGUER\220 LA MIA STRADA. PERMESSOO..", - "-COME?", - "LA VERIT\267, PENSANDOCI MEGLIO, CREDO DI NO", - "DIMI, OH ERUDITO FILOSOFO, C'\324 QUALCUNA RELAZIONE CAUSA-EFETTO TRA LA VELOCIT\267 E LA PANCETA?", - "VA BENE, SMETTILA. COMUNQUE NON SO PERCHE HO DETTO QUESTO", - "COSA FAI QU\336 FILOSOFANDO, CHE NON STAI MANGIANDO GENTE?", - "COME MAI?", - "SENTI, PUOI RIPETERE QUELLO DI \"INCLINAZIONI PRE-EVOLUTIVE\"?", - "SI SI, QUELLA STORIA CHE MI HAI RACCONTATO PRIMA. PERCHE NON HO CAPITO MOLTO BENE.", - "NO, MEGLIO NON DICO NULLA, NON VOGLIO METTERE IL COLTELLO NELLA PIAGA...", - "SI, MI DICA?", - "SI, CHE SUCCEDE?", - "AH, ADESSO CHE CITA IL SOGGETTO GLI DIR\343 CHE...", - "", - "AH.., COSA SUCCEDEREBBE SE UN VAMPIRO PRENDEREBBE LA RICETA..", - "NIENTE. SENTI, QUESTO SEMBRA UN POSTICCIO MESSO SUL COPIONE PER FINIRE PRESTO IL VIDEO-GIOCO?. BENE, FORSE, NO", - "\324 VUOTO!", - "PERCHE HAI RUBATO IL MIO AMORE, B.J., SENZA LEI LA MIA VITA NON HA SENSO", - "-IL SUO CERVELLO?!", - "NO NIENTE, MA CREDO CHE ALLA FINE IL TUO PICCOLINO MOSTRO MI HA FATTO ARRABBIARE", - "SANTA MADONNA AIUTAMI!", - "NON TE LA CAVEREI. SICURO CHE APPARISCE SUPERMAN E MI LIBERA!", - "CHE SCHIFFO DI VIDEO-GIOCO NEL CUI MUORE IL PROTAGONISTA", - "UN ATTIMO, COSA SUCCEDE COL MIO ULTIMO DESIDERIO?", - "-HA,HA! ORA SONO IMMUNIZZATO CONTRO TE, MALEDETTO DEMONIO. QUESTA SIGARETTA \324 UNA POZIONE ANTI-VAMPIRI CHE MI HA DATTO VON BRAUN", - "SI CERTO. MA NON RIUSCIRAI MAI A FARMI DIRTI LA RICETA", - "POSSO SOPPORTARE LA TORTURA, ANZI CREARLA", - "-NO, PER FAVORE!- PARLER\220, MA NON FARMI QUESTO!", - "BENE, TI HO GI\267 DETTO QUELLO CHE VOLEVI SAPERE. ORA LIBERA B.J. E ME, E LASCIACI PERDERE", - "-B.J-.! COSA FAI QU\336? DOV'\324 DRASCULA?", - "CHE PERVERSO! SOLTANTO PERCH'\324 NOBILE PENSA CHE HA IL DIRITTO SU TUTTI QUANTI", - "ABASSO LA ARISTOCRAZIA!", - "FORZA I POVERI DEL MONDOOO...", - "E QUELLO CHE VEDO \324 CHE TI HA INCATENATO ANZI CON LUCCHETTO", - "O.K., NON AVRAI UNA FONCINA?", - "BENE BENE, NON PRENDERTELA COS\336, CI PENSER\220 IO", - "EH, BARISTA", - "COME VA LA PARTITA?", - "CHI?", - "MA NON VEDI CHE DRASCULA \324 QU\336?", - "ANDIAMO A UCCIDERLO", - "SERVIMI UN DRINK..", - "NIENTE. HO DIMENTICATO COSA VOLEVO DIRTI", - "O\247MI\247SERVI\247UN\247DRINK\247O\247MI\247METTO\247A\247SUONARE\247IL\247PIANOFORTE", - "QUANTO MANCA PER LA FINE DELLA PARTITA?", - "BUONA SERA", - "COME VA IGOR? VAI CON LA GOBBA? -HI,HI,HI,CHE BUONO!", - "CHE STAI FACENDO?", - "NO", - "ALLORA METTITI GLI OCCHIALI", - "COSA \324 QUELLA DELLA ORGIA SOPRANNATURALE?", - "VA BENE, NON COTINUARE, MI FACCIO IDEA", - "NON POTREI DIRMI DOV'\324 DRASCULA?", - "DAIII, PER FAVORE", - "PER CHE NO?", - "AH, MA DORME DI NOTTE?", - "BENE, ALLORA IN BOCCA IL LUPO CON I REDDITI", - "DEVO PROPRIO PARLARE CON LUI", - "EOOOO, SCHELETROOO!", - "OH DIO! UN MORTO CHE PARLA!", - "RACCONTAMI. COME MAI SEI VENUTO QU\336?", - "E PER CHE DRASCULA VUOLE CREARE UN MOSTRO?", - "COME TI CHIAMI, AMICO SCHELETRO?", - "SENTI, NON VUOI QUALCOSA DA MANGIARE?", - "DEVI AVERE LO STOMACO VUOTO .- HI,HI,HI!", - "LA VERIT\267 \324 CHE NON MI VA DI PARLARE ADESSO", - "VANFFAN ( BIP ) FIGLIO DI .......( BIIP ).. VAI A FARE....( BIIIP )", - "IO LA AMAVO DAVVERO. O.K., SONO D'ACCCORDO CHE NON ERA MOLTO INTELLIGENTE, MA NESSUNO \324 PERFETTO, NO?", - "ANZI, AVEVA UN CORPO DA PAURA", - "ORMAI NON SAR\343 PI\353 QUELLO DI PRIMA .MI RICHIUDER\343 IN UN MONASTERO, E LASCIER\343 LA MIA VITA PERDERE", - "NIENTE POTR\267 FARMI USCIRE DI QUESTA MISERIA PERCHE...", - "DI CHI? DI CHI?", - "VOGLIO ESSERE PIRATA", - "VOGLIO ESSERE PROGRAMMATORE", - "RACCONTAMI QUALCOSA SU GARIBALDI", - "CONTINUER\343 A GIOCARE E DIMENTICHER\343 CHE VI HO VISTI", - "MA CHI AVR\267 PENSATO QUESTA SCIOCHEZZA!", - "\324 UNA BORSA COME QUELLA DI MIA NONNA", - "MA CHE FIGO SONO!", - "PI\353 MI VEDO PI\353 MI PIACCIO", - "E POI COME MI CHIUDO?", - "PRIMA DEVO APRIRMI, VERO?", - "ST\343 BENE DOVE SONO", - "MI HO GI\267 PRESSO", - "CIAO IO", - "ME GLI INDOSSER\343 QUANDO SIA LA OCCASIONE OPORTUNA", - "NON VEDO NIENTE DI SPECIALE", - "\324 BENE DOV'\324", - "E PER CHE?", - "NON CE LA FACCIO", - "CIAO TU", - "\324 IL SEPOLCRO DELLO ZIO PEPPINO", - "EOOOO, ZIO PEPPINOOOO!", - "NO.NON VOGLIO TAGLIARMI UN' ALTRA VOLTA", - "-EHEM,EHEM..!", - "GNAMM, EMMM,!", - "-SI, COF, COF!", - "GUARDA, C'\324 UNA GOMMA QU\336 ATTACATA", - "\324 IL TELEFONINO CHE MI HANNO REGALATO A NATALE", - "COM'\324 ALTO", - "ESCI AL BALCONE GIULIETTA!", - "TU SEI LA LUCE CHE ILLUMINA LA MIA VITA!", - "EH, PORTA, CHE C'\324?", - "EOOOO, SPENDITRICE DI TABACCO DI TRANSILVANIAAA", - "\324 UNA SPENDITRICE DI TABACCO", - "HO UN'ALTRA MONETA DENTRO", - "NO. HO DECISSO SMETTERE DI FUMARE E DI BERE", - "DA OGGI SAR\343 SOLTANTO PER LE DONNE", - "QUESTO \324 UNA TRUFFA! NON \324 USCITO NULLA", - "ALLA FINE!", - "CHE TI HO DETTO?, UN BAULE", - "CIAO BAULE, TI CHIAMI COME MIO CUGINO CHE SI CHIAMA RAUL..E", - "HO TROVATO LA BORSA DI B.J.", - "MIO DIO, NON MI RIFLETTO, SONO UN VAMPIRO!", - "...AH, NO, \324 UN DISEGNO", - "SPECCHIO DELLE MIE BRAME: CHI \220 ILPI\351 BELLO DEL REAME?", - "NON VUOLE APRIRMI", - "MOLTO BENE. MI HO MESSO I TAPPI", - "\324 UN DIPLOMA DI CACCIA-VAMPIRI OMOLOGATO DALLA UNVERSIT\267 DI CAMBRIDGE", - "NO. MANCANO ANCORA GLI INGREDIENTI, NON MERITA LA PENA CHE SIA SVEGLIATO", - "NON HO SOLDI", - "\324 UNA LAMPADA BRITANICA", - "BARISTA! AIUTAMI!", - "HA COMPARITO UN VAMPIRO ED HA PRESSO LA MIA FIDANZATA", - "MA NON MI AIUTER\267", - "MORTA? CHE VUOLE DIRE?", - "- EHEM!", - "UN VAMPIRO HA SEQUESTRATO LA RAGAZZA DELLA 506!", - "DEVI AIUTARMI!", - "NON SAI SUONARE NESSUNA DI \"ELIO E LE STORIE TESSE\"", - "COME TI SOPPORTI, SUONANDO SEMPRE LO STESSO?", - "ALLORA COME MI SENTI?", - "PRESTAMI I TAPPI", - "DAI, TE LI RESTITUISCO SUBITO", - "DAIIII...", - "CIAO. DEVO UCCIDERE UN VAMPIRO", - "", - "COSA DICI? IN TRANSILVANO?", - "CHI \324 LO ZIO PEPPINO?", - "MA CHE SUCCEDE CON DRASCULA?", - "CHI \324 VON BRAUN?", - "E PER CHE NON LO FA?", - "E DOVE POSSO TROVARE VON BRAUN?", - "GRAZIE E CIAO, SOGNI D'ORO", - "SAR\267 MEGLIO BUSSARE PRIMA", - "\324 LEI IL PROFESSORE VON BRAUN?", - "E MI POTREBBE DIRE DOVE POSSO ...?", - "NON CREDO SIA IL NANNO GANIMEDI", - "-PROFESSORE!", - "AIUTAMI! LA VITA DEL MIO AMORE DIPENDE DI LEI!", - "VA BENE, NON HO BISOGNO DEL SUO AIUTO", - "O.K. ME NE VADO", - "NON AVERE PAURA. INSIEME VINCEREMO DRASCULA", - "ALLORA PER CHE NON MI AIUTA?", - "IO CE LE HO", - "SI CE LE HO", - "D'ACCORDO", - "...EHH...SI", - "VENGO A RIENTRARE A QUESTA CABINA", - "SONO PRONTO PER FARE LA PROVA", - "VA BENE, VECCHIETO. SONO VENUTO PER IL MIO SOLDI", - "NO, NIENTE. ME NE GI\267 ANDAVO", - "SCUSA", - "TI \324 INTERESANTE QUESTO LIBRO? HA PARTITURE DI TCIAKOWSKY", - "COME POSSO UCCIDERE UN VAMPIRO?", - "NON TI HANNO DETTO CHE NON \324 BUONO DORMIRE IN CATTIVA POSIZIONE?", - "\324 QUELLO CHE SEMPRE DICE MIA MADRE", - "PER CHE DRASCULA NON FU RIUSCITO A UCCIDERTI?", - "E COSA FU?", - "BENISSIMO! HA LEI LA POZIONE DI IMMUNIT\267...!", - "ALLORA", - "MOLTO BENE", - "MI PUO RIPETERE COSA BISOGNO PER QUELLA POZIONE?", - "VADO VIA VELOCE A TROVARLO", - "SENTA, COSA \324 SUCCESO CON IL PIANISTA?", - "HO GI\267 TUTTI GLI INGREDIENTI DI QUESTA POZIONE", - "UNA DOMANDA: COSA \324 QUELLA DI ALUCSARD ETEREUM?", - "DICA, DICA..", - "E DOV'\324 QUELLA GROTTA?", - "CHE C'\324? NON AVETE TRIBUNALE?", - "...MA ...E SE TROVO PI\353 VAMPIRI?", - "\324 UN VAMPIRO CHE NON MI FA PASSARE", - "SI ASSOMIGLIA A YODA, MA PI\353 ALTO", - "EH, YODA. SE MI FAI PASSARE TI DAR\343 CENTO LIRE", - "BENE, O.K., NON POSSO DIRTI NULLA", - "CIAO VAMPIRO, BELLA NOTTE, VERO?", - "TI HANNO DETTO QUALCHE VOLTA CHE TI ASSOMIGLII A YODA?", - "SEI UN VAMPIRO O UN DIPINTO ALL'OLEO?", - "MEGLIO NON DIRTI NIENTE, PERCHE POI TI ARRABBII", - "\324 CHIUSA CON LA CHIAVE", - "SE PROVO, LA GAZZA MI POTREI CAVARE UN OCCHIO", - "\324 CHIUSA! DIO MIO, CHE PAURA!", - "LE CERNIERE SONO OSSIDATE", - "LA DENTRO C'\324 SOLTANTO UN BARATOLO DI FARINA", - "QUESTO HA TOLTO L'OSSIDO", - "HO TROVATO UNA TALEA DI LEGNO DI PINO", - "PRENDER\343 QUESTO CH'\220 PI\353 GROSSO", - "BENE, CREDO DI POTERE TOGLIERMI QUESTO STUPIDO COSTUME", - "\"CORRIDOIO AI TORRIONI CHIUSO PER LAVORI IN CORSO. PER FAVORE, PER LA PORTA PRINCIPALE. SCUSATE PER IL DISTURBO\"", - "..\324 PALLIDO, HA DENTI CANINI, HA CIUFFO E UTILIZA MANTELLO...- SICURO CH'\324 DRASCULA!", - "B.J., B.J., STAI BENE?", - "SI, SO CH'\324 SCEMA MA MI SENTO SOLISSIMO", - "NON AVRAI UNA CHIAVE PER CASO, VERO?", - "- E SICURO CHE NON HAI UN GRIMALDELLO?", - "DAMI UNA FONCINA. VADO A FARE COME MCGYVER", - "NON MUOVERTI, TORNO SUBITO", - "- MANAGIA!- SI \324 ROTTA!", - "OLE, ANCHE MI HO FATTO LA BARBA!", - "SI, CARO?", - "NON ARRIVA", - "IL PIANISTA NON C'\324", - "UN DRINK TRANSILVANO", - "ANCORA NON HO CAMERA", - "SEMBRA CHE FU RISUCCHIATO NELLO SCARICO DELLA VASCA E HA DECISO APRIRE UN BAR", - "\324 UBRIACO PERSO", - "QUESTI CAPELLI.... CREDO CHE MI FANNO RICORDARE A QUALCUNO", - "\324 UNO SCHELETRO OSSUTO", - "GUARDA! MIGUEL BOSE!", - "\324 ADDORMENTATO. SAREBBE UN PECCATO SVEGLIARGLI", - "\324 PI\353 BRUTTO CHE BEGNINI", - "UN FERETRO DI LEGNO DI PINO", - "MI TAGLIER\267 A FETTINI, COME UN SALSICCIOTTO", - "NON MI PIACCIONO I PENDOLI. PREFERISCO LE CARCIOFE", - "LE MIE MANI SONO LEGATE. NON CE LA FAR\343", - "\324 OVVIO CH'\324 UNA PORTA SEGRETA", - "MI IGNORANO", - "-DAIII!", - "NEL PRIMO COPIONE SI MUOVEVA, MA IL VIDEO-GIOCO \220 USCITO DAL BUDGET E NON HANNO POTUTO PAGARMI UNA PALESTRA E NON SONO GONFFIATO", - "SEMBRA CH'\324 UN P\343 ALLENTATA DAL MURO", - "NON CREDO CHE MI SIA UTILE. \324 TROPPO UMIDA PER ACCENDERLA.", - "AL LATO OVEST? -N\324 PAZZO, CHI SA CHE CI SAR\267 LI!", - "HA DEI BELLI DISEGNI TRANSILVANI", - "", - "CHE PENA CHE NON CI SIA DENTRO UN AGNELLINO ARRROSTANDOSI", - "LA ULTIMA VOLTA CHE APRII UN FORNO, LA CASA SALT\220 PER ARIA", - "LO SCUDO DELLA SCUADRA DI CALCIO DI TRANSILVANIA", - "E PER CHE? PER INDOSARLA SULLA TESTA?", - "NON CREDO CHE I CASSETI SIANO DI QUELLI CHE SI APPRONO", - "NON VOGLIO SAPERE IL CIBO CHE CI SAR\267 LA DENTRO!", - "HO L'IMPRESSIONE CH'\324 IMPRESSIONISTA", - "LA NOTTE SI IMPADRONA DI TUTTI QUANTI... CHE PAURA?", - "\324 OSTACOLATA", - "\324 IL RE, NON LO AVEVI IMAGINATO?", - "NO, NE UNO A CASA, ANZI GLI DO DA MANGIARE", - "UNA SCAFFALATURA CON LIBRI ED ALTRE COSE", - "E A CHI CHIAMO A QUESTE ORE?", - "\"COME FARE LA DECLARAZIONE DI REDDITI\"- CHE INTERESSANTE!", - "NE HO UNO A CASA, CREDO CH'\324 UN BEST-SELLER MONDIALE", - "UNA CHIAVE COMPLETAMENTE NORMALE", - "MI SA QHE QUESTA NON \220 DI QU\336", - "EH, SONO PATATINE FRITE A FORMA DI DENTI CANINI ! MI AFASCINA", - "NON CREDO CHE SIA IL MOMENTO MIGLIORE PER METTERSI A MANGIARE DOLCI, L'ESSERE PI\353 CATTIVO DEL MONDO ha nelle sue mani la mia fidanzzata", - "COME MI ST\343 DIVERTENDO UCCIDENDO VAMPIRI CON QUESTO!", - "VEDIAMO SE APPARISCE UN ALTRO PRESTO", - "NO, DEVE ESSERE CON UN VAMPIRO SPORCO E SCHIFFOSO COME QUELLO DI PRIMA", - "\324 L'AUTENTICA PARRUCA CHE UTILIZZ\343 ELVIS QUANDO DIVENT\343 PELATO", - "\220 FARINA MA NON POSSO DIRE MARCHE", - "FORSE IN UN ALTRO MOMENTO. OK?", - "\220 UNA ASCIA BUONISSIMA, CHE PENA CHE NON CI SIA QU\336 VICINO NESSUNA TESTA DI VAMPIRO", - "NO. NEL FONDO SONO UNA BRAVISSIMA PERSONA", - "\324 IL DEODORANTE DELLA TACHER -HI,HI,HI!", - "\324 UN MANTELLO ABBASTANZA CARINO", - "", - "COME TUTTI I RAMI DI TUTTI GLI ALBERI DEL MONDO, CIO\324 MICA SPEZIALE", - "OH, INCREDIBILE!- UNA CORDA IN UNA AVVENTURA GRAFICA!", - "MI DOMANDO A CHE SERVE...", - "UNA CORDA LEGATA A UNA BRANCA, O UNA BRANCA LEGATA A UNA CORDA, DIPENDE COME SI GUARDI", - "SEMBRA CHE QUESTA GAZZA HA CATIVE INTENZIONI", - "DAI.., NON LA DICO NULLA CHE POI SI ARRABBIA", - "SEMBRA ESSERE MORTA, MA NON \220 VERO - EH?", - "NESSUN ANIMALE \220 STATO MALTRATO DURANTE LE RIPRESE DI QUESTO VIDEO-GIOCO", -}, -}; - -const char *_textd[][79] = { -{ - "", - "HEY IGOR, HOW IS EVERYTHING GOING?", - "IT'S ALWAYS THE SAME STORY EVERYTIME THERE'S A GOOD GAME ON THE SATELLITE! ANYWAY, WE'LL GO WATCH IT IN THE BAR, AS USUAL", - "IGOR LISTEN CAREFULLY MAN, WE ARE GOING TO START WITH PHASE NUMBER ONE OF MY PLAN TO CONQUER THE WORLD", - "FIRST WE'LL CAPTURE ONE OF THE LIGHTNINGS AND WE'LL DEMAGNETIZE IT WITH OUR INDIFIBULATOR. THE ELECTRICITY WILL COME THROUGH TO MY MONSTER AND HE'LL GET ALIVE!", - "IF EVERYTHING WORKS OUT ALL RIGHT, THIS WILL BE THE BEGINNING OF A GREAT ARMY THAT WILL CONQUER THE WORLD FOR ME. HA, HA", - "THE MONSTERS WILL DESTROY ALL THE ARMY'S WEAPONS IN THE WORLD, MEANWHILE, WE'LL BE SAFE IN THE PIECES OF LAND I BOUGHT IN GIBRALTAR", - "WE'LL SET UP A COUP. GOVERNMENTS ALL OVER THE WORLD WILL BE UNCOVERED AND THEIR COUNTRIES WILL SURRENDER TO ME!", - "I'LL BECOME THE FIRST BAD GUY IN HISTORY TO MAKE IT ! HA, HA!", - "I'M NOT TALKING TO YOU, IDIOT! I'M JUST GIVING YOU THE PLOT. ALL RIGHT, EVERYTHING READY?", - "THE TIME HAS COME! TURN ON THE ALKALINE BATTERIES' SWITCH", - "DAMNED IT! WHAT WENT WRONG?", - "ARE YOU SURE YOU CHECKED IT ALL AND THERE WAS NOTHING MISSING? YOU'VE BEEN LATELY MESSING AROUND WITH THAT STUFF ABOUT TAXES AND I DON'T KNOW MAN...", - "YOU STUPID THING! YOU FORGOT TO CONNECT THE INDIFIBULATOR. THE SCREWS HAVE PROBABLY MAGNETIZED AND HIS BRAIN BURNT", - "YOU ARE DEAD, YOU ARE DEAD...WAIT TILL I GET YOU!", - "SHUT UP! I'LL GET ANOTHER BRAIN TOMORROW AND THEN WE WILL REPEAT THE EXPERIMENT", - "THIS TIME I'LL GET A WOMAN'S BRAIN. SHINY AND NOT USED YET...HA, HA, HA, GOODIE ONE!", - "SO WHAT? I'M THE BAD GUY, RIGHT? SO I CAN BE AS FULL OF MACHISMO AS I WANT, ALL RIGHT? AND IF YOU SAY SOMETHING AGAIN I'LL TURN YOUR HUMP BACK TO FRONT!", - "HA, HA, HA. YOU FELL TOOO!! NOW YOU ARE GOING TO PAY FOR DARING TO FIGHT AGAINST ME! IGOR, TAKE HIM TO THE PENDULUM OF DEATH!", - "AND SO, TELL ME, YOU STUPID HUMAN. HOW COME YOU WANT TO DESTROY ME?", - "THAT'S BEAUTIFUL!. IF IT WASN'T BECAUSE IT MAKES ME LAUGH, I WOULD CRY", - "OUR GIRLFRIEND'S BRAIN TO HELP ME CONQUERING THE WORLD", - "YES, SURE! I'LL TAKE IT FROM HER AND GIVE IT TO MY FRUSKYNSTEIN. THE WORLD WILL BE MINE WITH IT, HA, HA", - "WHAT!? YOU'RE DEAD, MAN! I'M GOING TO...YOU REALLY GOT ME ANGRY MAN...COME ON, PREPARE TO DIE!", - "HA, HA, HA. NOT EVEN IN YOUR WILDEST DREAMS!", - "YES, ISN'T IT? HA, HA", - "ALL RIGHT, ALL RIGHT. BUT DO IT QUICKLY, OK?", - "PUT THAT CIGARETTE OUT NOW! I CAN'T STAND YOU ANYMORE!", - "AND SO, DOES THAT BREW HAVE THE OPPOSITE EFFECT?", - "WELL, WE'LL SEE THAT", - "OK, LET'S SEE IT. IGOR, BRING ME THE CD \"SCRATCHING YOUR NAILS ALL OVER THE BLACKBOARD\"", - "NO WAY. THE GIRL STAYS WITH ME. YOU RE STAYING THERE UNTIL THE PENDULUM CUTS YOU INTO THIN SLICES. HA, HA, HA", - "MAN I'M I JUST BAD... COME ON IGOR, LET'S MAKE THE BREW AND CONQUER THE WORLD", - "WHAT HAPPENS NOW?", - "YES, WHAT?...OH, DAMNED, THE GAME!", - "I FORGOT ABOUT THAT. GET THE GIRL AND LET'S GO AND WATCH IT. WE CAN CONQUER THE WORLD LATER", - "THANKS MAN, I WAS THIRSTY", - "OH, THE CRUCIFIX!!...THE CRUCIFIX...!", - "I DIDN'T NOTICE ABOUT THAT BEAUTIFUL CRUCIFIX!", - "LEAVE ME ALONE!, I'M WATCHING THE GAME", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "HI BLIND MAN. HOW IT'S GOING?", - "HOW DO YOU KNOW I'M A FOREIGNER?", - "YOU LOOK BLIND. YOU'RE WEARING DARK GLASSES LIKE STEVIE WONDER", - "LOOK, I'M SORRY, I DIDN'T KNOW YOU COULD SEE", - "BUT HAVEN'T YOU JUST TOLD ME YOU WEREN'T BLIND", - "BUT IF YOU CAN'T SEE", - "OOOOKAY. SORRY. IN THAT CASE, HI THERE SIGHTLESS PERSON", - "I'M JOHN HACKER. YOU MUST BE ONE OF THOSE CHARACTERS WHO WILL HELP ME OUT IN EXCHANGE FOR AN OBJECT. AREN'T YOU? EH? AREN'T YOU?", - "UUUUM, EXCUSE ME FOR ASKING BLIN... SIGHTLESS PERSON! BUT WHAT SORT OF JOB IS THAT, TO GIVE SICKLES IN EXCHANGE FOR MONEY WHILE YOU PLAY THE ACCORDION?", - "AH YES, I SUPPOSE THAT'S TRUE. GOODBYE SIGHTLESS PERSON... BLIND MAN", - "HERE IS THE LARGE AMOUNT OF MONEY YOU ASKED ME FOR", - "YOU BETTER HAVE HAD", - "HI THERE FOREIGNER", - "AND HOW DO YOU KNOW I'M BLIND?", - "AND I'M NOT KIDDING YOU BUT YOUR'S ARE LIKE WOODY ALLEN'S", - "NO, I CAN'T SEE", - "AND I'M NOT", - "OH OF COURSE. JUST COS I CAN'T SEE, YOU ACCUSE ME OF BEING BLIND", - "HI THERE FOREIGNER! WHAT ARE YOU DOING IN TRANSYLVANIA?", - "THAT'S RIGHT, FOREIGNER. IN EXCHANGE FOR A LARGE SUM OF MONEY I'LL GIVE YOU A SICKLE FOR WHEN YOU MIGHT NEED IT", - "SHHHH, I'M A SICKLES TRADER, THAT'S WHY I HAVE TO HIDE", - "BECAUSE YOU TOLD ME BEFORE, DIDN'T YOU?", - "THANKS FOREIGNER. HERE'S THE SICKLE IN EXCHANGE. YOU'LL FIND IT REALLY USEFUL LATER ON, HONESTLY", -}, -{ - "", - "\250COMO VA TODO, IGOR?", - "\255SIEMPRE QUE HAY UN BUEN PARTIDO EN LA PARABOLICA PASA LO MISMO! EN FIN, IREMOS A VERLO AL BAR COMO DE COSTUMBRE", - "AHORA IGOR, ATIENDE. VAMOS A REALIZAR LA FASE 1 DE MI PLAN PARA CONQUISTAR EL MUNDO", - "PRIMERO CAPTAREMOS UNO DE LOS RAYOS DE LA TORMENTA Y LO DESMAGNETIZAREMOS CON NUESTRO INDIFIBULADOR. LA ELECTRICIDAD PASARA A MI MONSTRUO \255Y LE DARA VIDA! ", - "SI TODO SALE BIEN ESTE NO SERA MAS QUE EL PRIMERO DE UN INMENSO EJERCITO QUE CONQUISTARA EL MUNDO PARA MI, JA, JA, JA", - "LOS MONSTRUOS DESTRUIRAN TODAS LAS ARMAS DE TODOS LOS EJERCITOS DEL MUNDO, MIENTRAS NOSOTROS NOS REFUGIAMOS EN UNOS TERRENOS QUE HE COMPRADO EN GIBRALTAR", - "ENTONCES, DAREMOS UN GOLPE DE ESTADO, LOS GOBIERNOS DEL MUNDO NO TENDRAN CON QUE PROTEGERSE, Y PONDRAN SUS PAISES A MIS PIES", - "\255SERE EL PRIMER MALO EN LA HISTORIA QUE LO CONSIGA! \255JUA, JUA, JUA!", - "\255A TI NADA, IDIOTA! ESTOY EXPONIENDO LA TRAMA. BIEN \250ESTA TODO LISTO?", - "\255LLEGO EL MOMENTO, ENTONCES! \255DALE AL INTERRUPTOR DE LAS PILAS ALCALINAS! ", - "\255MALDITA SEA! \250QUE ES LO QUE HA PODIDO FALLAR?", - "\250SEGURO QUE LO REVISASTE BIEN Y NO FALTABA NADA? ULTIMAMENTE ESTAS CON ESO DE LA RENTA QUE NO VES UN PIJO A DOS METROS", - "\255IDIOTA, NO HABIAS CONECTADO EL INDIFIBULADOR! LOS TORNILLOS SE HABRAN MAGNETIZADO Y SE LE HABRA QUEMADO EL CEREBRO", - "ESTAS MUERTO, ESTAS MUERTO, COMO TE COJA...", - "\255A CALLAR! MA\245ANA IRE A POR OTRO CEREBRO Y REPETIREMOS EL EXPERIMENTO ", - "NO. ESTA VEZ TRAERE UNO DE MUJER, PARA QUE ESTE NUEVECITO Y SIN ESTRENAR. JA, JA, JA, QUE MALISIMA DE CHISTA", - "\250Y QUE? YO SOY EL MALO Y SOY TODO LO MACHISTA QUE QUIERA \250ENTENDIDO? Y COMO ME VUELVAS A RECHISTAR TE TRAGAS LA CHEPA ", - "JA, JA, JA. OTRO QUE HA CAIDO. AHORA VAS A PAGAR TU OSADIA DE QUERER ACABAR CONMIGO. \255IGOR, AL PENDULO DE LA MUERTE!", - "DIME, HUMANO ESTUPIDO, \250COMO ES QUE TE HA DADO POR QUERER DESTRUIRME? ", - "\255QUE BONITO!, ME PONDRIA A LLORAR SI NO FUERA PORQUE ME HACE GRACIA", - "A TU NOVIA LA NECESITO PARA QUE ME AYUDE CON SU CEREBRO A CONQUISTAR EL MUNDO", - "\255SI, JA! SE LO QUITARE Y SE LO PONDRE A MI FRUSKYNSTEIN, Y CON EL DOMINARE EL MUNDO, JA, JA, JA", - "\255\250QUE?! \255ESTAS MUERTO, ESTAS MUERTO! TE VOY A... ME HAS TOCADO LAS NARICES, VAMOS. \255PREPARATE A SER MATADO!", - "JA, JA, JA. QUE TE CREES TU ESO", - "SI, \250VERDAD? JA, JA, JA ", - "AH, ESTA BIEN, PUEDES FUMARTE EL ULTIMO CIGARRILLO, PERO DEPRISITA", - "APAGA YA ESE CIGARRILLO, ME TIENES HARTO YA", - "Y DIME, \250ESA POCION TIENE EL EFECTO CONTRARIO?", - "ESO YA LO VEREMOS...", - "BUENO, A VER SI ES VERDAD. IGOR, TRAE EL COMPACT DISC DE U\245AS ARRASCANDO UNA PIZARRA", - "ESO NI SO\245ARLO. LA CHICA SE QUEDA CONMIGO, Y TU TE QUEDAS AHI HASTA QUE EL PENDULO TE CORTE EL RODAJITAS. JA, JA, JA", - "PERO QUE MALO QUE SOY, VAMOS IGOR, VAMOS A PREPARAR LA POCION Y CONQUISTAR EL MUNDO", - "\250QUE PASA AHORA?", - "SI, \250QUE PASA?... \255ANDA, EL PARTIDO!", - "SE ME HABIA OLVIDADO. COGE A LA CHICA Y VAMONOS A VERLE. YA CONQUISTARE EL MUNDO DESPUES", - "GRACIAS MACHO, TENIA SED", - "\255ArgH! \255ESE CRUCIFIJO! \255ESE CRUCIFIJO!...", - "QUE BONITO ES ESE CRUCIFIJO, NO ME HABIA YO FIJADO", - "DEJAME, QUE ESTOY VIENDO EL FUTBOL", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "Hola ciego. \250Que tal?", - "\250Como sabes que soy extranjero?", - "Pareces un ciego. Tienes gafas como serafin zubiri, hablas mirando al frente como Stevie Wonder...", - "Bueno, perdona. No sabia que vieses.", - "\250Pero no me acabas de decir que no eres ciego?", - "\255Pero si no ves!", - "Vaaaale. Perdona. En ese caso: Hola invidente.", - "Soy John Hacker, y estoy jugando al Drascula. Tu debes ser el tipico personaje que me ayudara a cambio de un objeto. \250A que si? \250Eh? \250A que si?", - "Em... Perdona que te pregunte cieg..\255Invidente!. Pero... \250Que clase de profesion es la tuya, de dar hoces a cambio de dinero, mientras tocas el acordeon?", - "Ah, si. Es verdad. Adios invidente...(ciego)", - "Ahi tienes la cuantiosa cantidad de dinero que me pediste.", - "Mas te vale.", - "Hola extranjero.", - "Y tu... \250Como sabes que soy ciego?", - "Y tu hablas como el hijo de Bill Cosby y no me meto contigo.", - "No, si no veo.", - "Y no lo soy.", - "\255Oh, claro! Como no veo se me tacha de ciego \250no?", - "\255Hola Extranjero! y \250que haces en Transilvania?", - "Correcto extranjero. A cambio de una cuantiosa suma de dinero, te dare una hoz, para cuando te haga falta.", - "Shhhhhh. Soy traficante de hoces, tengo que disimular.", - "Porque me lo has dicho antes \250no?", - "Gracias extranjero. Aqui tienes tu hoz a cambio. Un objeto que te sera muy util algo mas adelante... de verdad.", -}, -{ - "", - "WIE GEHTS, WIE STEHTS, IGOR ?", - "IMMER WENN auf kabel EIN GUTES SPIEL KOMMT, PASSIERT DAS GLEICHE. NAJA, DANN GUCKEN WIR ES UNS EBEN WIE IMMER IN DER KNEIPE AN", - "JETZT PASS AUF, IGOR. WIR WERDEN JETZT PHASE 1 MEINES WELTEROBERUNGSPLANS STARTEN.", - "Pah, einige GEWITTERBLITZE, die wir MIT dem VIBROXATOR ENTMAGNETISIEREN. und der strom wird meinem MONSTERCHEN leben einhauchen.", - "WENN ALLES KLAPPT WIRD ER DER ERSTE SOLDAT EINER RIESIGEN ARMEE SEIN, DIE DIE WELT FueR MICH EROBERN WIRD, HARHARHAR", - "DIE MONSTER WERDEN ALLE WAFFEN IN DER GANZEN WELT VERNICHTEN WaeHREND WIR UNS AUF UNSERE LaeNDEREIEN ZURueCKZIEHEN, DIE ICH UNS AUF HELGOLAND GEKAUFT HABE.", - "DANN WERDEN WIR EINEN STAATSSTREICH MACHEN UND DIE REGIERUNGEN DIESER WELT WERDEN AUFGEBEN UND SICH MIR ZU FueSSEN WERFEN", - "ICH WERDE DER ERSTE BoeSE IN DER GESCHICHTE SEIN, DER DAS SCHAFFT, HUAHUAHUA !", - "GAR NICHTS, IDIOT ! ICH ERZaeHLE DIE HANDLUNG .O.K . IST ALLES FERTIG ?", - "ES IST ALSO SOWEIT !DRueCK AUF DEN SCHALTER MIT DEN ALKALI-BATTERIEN !", - "VERFLIXT NOCHMAL ! WAS IST DA SCHIEFGELAUFEN ?", - "BIST DU SICHER, DASS DU ALLES GECHECKT HAST ? SEIT NEUESTEM DENKST DU NUR NOCH AN DEINE EINKOMMENSERKLaeRUNG UND KRIEGST NICHTS MEHR MIT", - "DU IDIOT !DU HAST DEN VIBROXITOR NICHT EINGESCHALTET !JETZT SIND DIE SCHRAUBEN MAGNETISIERT UND IHM WIRD WOHL DAS GEHIRN VERBRANNT SEIN", - "DU BIST EIN TOTER MANN, NA WARTE, WENN ICH DICH KRIEGE...", - "HALT DIE KLAPPE !MORGEN HOLE ICH EIN NEUES HIRN UND WIR WIEDERHOLEN DAS EXPERIMENT", - "NEIN, DIESMAL BESORG ICH EIN FRAUENHIRN, DASS NOCH GANZ FRISCH UND UNBENUTZT IST, HAR,HAR,HAR, SUPERJOKE !", - "NA UND ? ICH BIN DER BoeSE UND DER SUPER-MACHO ODER WAS ? UND WENN DU MIR NOCHMAL WIDERSPRICHST KANNST DU DEINEN BUCKEL SCHLUCKEN", - "HARHARHAR,SCHON WIEDER EINER. DU WARST SO DREIST, MICH UMBRINGEN ZU WOLLEN. DAS WIRST DU JETZT BueSSEN. IGOR! ZUM TODESPENDEL MIT IHM !", - "SAG MAL DU DUMMES MENSCHLEIN, WIESO WOLLTEST DU MICH ZERSToeREN ?", - "ACH WIE SueSS !ICH KoeNNTE GLATT ANFANGEN ZU HEULEN, WENN ES NICHT SO LUSTIG WaeRE", - "DEINE FREUNDIN BRAUCHE ICH NOCH, DAMIT SIE MIR MIT IHREM HIRN DABEI HILFT, DIE WELT ZU EROBERN", - "JA, HA !ICH WERDE ES RAUSREISSEN UND ES FRUNKSFENSTEIN GEBEN UND DANN WERDE ICH DIE WELT EROBERN,HARHARHAR", - "WAS ? !DU BIST EIN TOTER MANN! ICH WERDE DICH... DU HAST MICH VERaePPELT,GANZ KLAR . MACH DEIN TESTAMENT!", - "HARHARHAR, GLAUB DU DAS MAL ", - "JA, WIRKLICH ? HARHARHAR", - "JA, SCHON GUT, RAUCH DIR NOCH EINE LETZTE ZIGARETTE, ABER RUCKZUCK", - "MACH MAL DIE ZIGARETTE AUS. MIR IST SCHON SCHLECHT", - "UND SAG MAL, DIESE MISCHUNG HAT DIE GEGENWIRKUNG ?", - "DAS WERDEN WIR JA MAL SEHEN...", - "NA, MAL GUCKEN OB DAS STIMMT, IGOR., BRING MAL DIE CD MIT DEN DEM SOUND VON kratzenden FINGERNaeGELN AUF EINER SCHULTAFEL", - "NICHT IM TRAUM. DAS MaeDCHEN BLEIBT BEI MIR UND DU BLEIBST WO DU BIST, BIS DICH DAS PENDEL IN LECKERE SCHEIBCHEN SCHNEIDET, HARHAR", - "WIE BoeSE ICH DOCH BIN. KOMM IGOR, WIR BEREITEN DIE MISCHUNG ZU UND EROBERN DANN DIE WELT", - "WAS IST DENN JETZT WIEDER LOS ?", - "JA, WAS IST LOS ?...VERDAMMT, DAS SPIEL !", - "DAS HAB ICH GLATT VERGESSEN. NIMM DAS MaeDCHEN UND LASS UNS DAS SPIEL ANGUCKEN GEHEN . DIE WELT EROBERN WIR DANACH.", - "DANKE, ALTER, ICH HATTE DURST", - "ARGHH! DAS KRUZIFIX DA ! DAS KRUZIFIX !", - "WIE SCHoeN DAS KRUZIFIX DA IST, HAB ICH GAR NICHT BEMERKT", - "LASS MICH, ICH GUCK DOCH GERADE FUSSBALL", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "Hallo Blinder. Wie gehts?", - "Woher weisst Du, dass ich nicht von hier bin ?", - "Du siehst wie ein Blinder aus . Du guckst beim Sprechen immer gerade aus, und dann diese Stevie-Wonder-Brille....", - "O.k,entschuldige. Ich dachte, du kannst nichts sehen", - "Aber hast Du mir nicht gerade gesagt, dass Du NICHT blind bist?", - "Ich denke, Du siehst nichts ?", - "Okaaay,okaay! Tut mir leid. Also wenn das so ist: Sehkranker ", - "Ich bin Heinz Hacker und spiele Drascula . Du bist bestimmt derjenige, der mir hilft und dafuer irgendwas haben will. Stimmts? Hae? Hab ich recht!?", - "aeh....Entschuldige die Frage, Blind-Sehkranker!Aber...Was hast Du fuer einen komischen Beruf, dass Du Sicheln verkaufst und dabei Akkordeon spielst!", - "Ach, klar, stimmt. Auf Wiedersehen Sehkranker...(Blinder)", - "Hier hast Du den Wahnsinnsbatzen Geld, um den Du mich gebeten hast", - "Das ist auch besser so!", - "Hallo Fremder!", - "Und Du...Woher willst Du wissen, dass ich blind bin?", - "Und Du bist der Sohn von Bill Cosby und ich werde mich nicht mit Dir anlegen", - "Nein, ich seh doch nichts!", - "Und ich bin es nicht", - "Na super! Nur weil ich nichts sehe bin ich direkt ein Blinder, oder was?", - "Hallo Fremder! Und was machst Du in Transylvanien?", - "Richtig, Fremder. Gegen einen Wahnsinnsbatzen Geld bekommst Du von mir eine Sichel damit Du eine hast, wenn Du eine brauchst.", - "Psssssst. Ich bin Sichel-Dealer, ich muss unentdeckt bleiben ", - "Warum hast Du mir das nicht vorher gesagt ?", - "Danke, Fremder. Hier hast du dafuer Deine Sichel. Sie wird Dir nachher noch nuetzlich sein...glaub mir !", -}, -{ - "", - "COMMENT VA TOUT, IGOR?", - "C'EST TOUJOURS LA M\322ME CHOSE QUAND IL Y A UN BON MATCH \267 LA PARABOLIQUE! ENFIN, ALLONS LE VOIR AU BAR, COMME D'HABITUDE", - "MAINTENANT, COUTE IGOR. NOUS ALLONS RALISER LA PHASE 1 DE MON PLAN POUR CONQURIR LE MONDE", - "D'ABORD, ON SAISIRA L'UNE DES FOUDRES DE L'ORAGE ET ON LA DMAGNTISERAIT AVEC l'INDIFUBULATEUR. LA COURANTE PASSERA DANS MON MONSTRE ET LUI DONNERA LA VIE!", - "SI TOUT VA BIEN CELUI-L\267 NE SERA QUE LE PREMIER D'UNE IMMENSE ARME QUE CONQURRA LE MONDE POUR MOI, HA! HA! HA! ", - "LES MONSTRES VONT ANANTIR TOUTES LES ARMES DE TOUTES LES ARMES DU MONDE, TANDIS QUE NOUS NOUS RFUGIONS DANS LES TERRAINS QUE J'AI ACHET \267 GIBRALTAR", - "ALORS, ON DONNERA UN COUP D'TAT. LES GOUVERNEMENTS DU MONDE N'AURONT PAS DE PROTECTION ET SES PAYS SERONT \267 MES PIEDS", - "JE SERAI LE PREMIER MALIN DE L'HISTOIRE \267 Y AVOIR RUSSI! -HOUA! HOUA! HOUA!", - "POUR TOI RIEN, IDIOT! JE PRSENTE LA TRAME. BIEN, TOUT EST PR\322T? ", - "LE MOMENT EST ARRIV\220, ALORS! -APPUIE DONC SUR L'INTERRUPTEUR DES BATTERIES ALCALINES! ", - "H\220LAS! QU'EST-CE QUE N'A PAS MARCH\220?", - "C'EST S\352R QUE TU L'AS BIEN R\220VIS\220 ET IL NE MANQUAIT RIEN? DERNI\324REMENT AVEC CETTE HISTOIRE DE LA RENTE TU N'Y VOIS GOUTTE", - "IDIOT! TU N'AVAIS PAS CONNECT\220 L'INFIBULATEUR! LES VIS SE SERONT MAGN\220TIS\220ES ET SA CERVELLE AURA BR\352L\220E", - "TU ES MORT, TU ES MORT, SI JE T'ATTRAPE...", - "TAIS-TOI! DEMAIN J'AURAI UNE AUTRE CERVELLE ET ON FERA L'ESSAI \267 NOUVEAU", - "NON, CETTE FOIS J'APPORTERAI UNE DE FEMME POUR QU'ELLE SOIT TOUTE NEUVE ET DE PREMI\324RE MAIN. HA! HA! HA! QUE MALIN DE XISTE", - "ET QUOI? JE SUIS LE MALIN ET TOUT LE SEXISTE QUE JE D\220SIRE, C'EST ENTENDU? SI TU ME R\220PLIQUES ENCORE JE TE FAIS ENGLOUTIR TA BOSSE", - "HA! HA! HA!. UN AUTRE QUI S'EST LAISS\220 PRENDRE. MAINTENANT TU PAIERAS CHER TON AUDACE DE VOULOIR EN FINIR AVEC MOI. -IGOR, AU PENDULE DE LA MORT!", - "DIS-MOI, HUMAIN STUPIDE, POURQUOI TU AS PENS\220 ME D\220TRUIRE? ", - "QUE C'EST BEAU! JE SANGLOTERAIS SI CE N'ETAIT PAS DR\342LE", - "J'AI BESOIN DE TA FIANC\220E POUR QU'ELLE M'AIDE \267 CONQU\220RIR LE MONDE AVEC SA CERVELLE", - "OUI, HA! JE LA LUI ARRACHERAI ET L'INSTALLERAI SUR MON FRUSKYNSTEIN, ET AVEC LUI JE VAIS MA\327TRISER LE MONDE, HA! HA! HA!", - "QUOI?! -TU ES MORT, TU ES MORT! JE VAIS TE... TU M'AS CASS\220 LE NEZ, ALLONS, -APPR\322TE-TOI \267 \322TRE TU\220!", - "HA! HA! HA! C'EST-CE QUE TU CROIS", - "OUI, N'EST-CE PAS? HA! HA! HA!", - "AH, C'EST BIEN! TU PEUX FUMER LA DERNI\324RE CIGARETTE, MAIS D\220P\322CHE-TOI!", - "\220TEINS D\220J\267 CETTE CIGARETTE, J'EN A RAS LE BOL!", - "ET DIS-MOIS, CETTE POTION, A-T-ELLE L'EFFET CONTRAIRE?", - "ON VERRA \200A...", - "EH BIEN, ON VERRA SI C'EST VRAI. IGOR, APPORTE LE COMPACT DISC D'ONGLES GRATTANT UN TABLEAU", - "N'Y PENSES PAS. LA FILLE RESTE AVEC MOI, ET TOI TU RESTERAS L\267 JUSQU'\267 QUE LA PENDULE TE COUPE EN PETITES TRANCHES. HA! HA! HA!", - "MAIS QUE JE SUIS MALIN. ON Y VA, IGOR, ALLONS PR\220PARER LA POTION ET CONQU\220RIR LE MONDE", - "QU'Y A-T-IL MAINTENANT?", - "OUI, QU'Y A-T-IL?... -TIENS, LE MATCH!", - "JE L'AVAIS OUBLI\220. PRENDS LA FILLE ET ALLONS LE VOIR. J'IRAI CONQU\220RIR LE MONDE PLUS TARD", - "MERCI MON VIEUX, J'AVAIS SOIF", - "ArgH! CE CRUCIFIX! -CE CRUCIFIX!...", - "C'EST BEAU CE CRUCIFIX, JE NE M'AVAIS PAS RENDU COMPTE", - "FICHE-MOI LA PAIX! JE REGARDE LE FOOT-BALL", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "BONJOUR, L'AVEUGLE. A VA?", - "POURQUOI TU SAIS QUE JE SUIS UN TRANGER?", - "TU PARAT UN AVEUGLE. TU AS DES LUNETTES COMME SERAFIN ZUBIRI ET TU PARLES EN REGARDANT DEVANT TOI, COMME STEVIE WONDER...", - "BON, EXCUSE-MOI. JE NE SAVAIS PAS QUE TU PUISSES VOIR.", - "MAIS, TU NE VIENS PAS DE ME DIRE QUE TU N'EST PAS AVEUGLE?", - "MAIS TU NE VOIS PAS!", - "A VA, A VA.... PARDONNE-MOI. DANS CE CAS-L: BONJOUR AVEUGLE.", - "JE SUIS JOHN HACQUER ET JE JOUE AU DRASCULA. TU ES SREMENT LE TYPIQUE PERSONNAGE QUI VA M'AIDER EN TROC D'UN OBJET. D'ACCORD? H? D'ACCORD?", - "EUH... AVEUGLE, UNE QUESTION! MAIS... QUEL GENRE DE MTIER C'EST LE TIEN? CELUI D'CHANGER DE FAUCILLES CONTRE DE L'ARGENT EN JOUANT DE L'ACCORDON?", - "AH, OUI! C'EST VRAI. AU REVOIR AVEUGLE...", - "VOIL LA GROSSE SOMME D'ARGENT QUE TU M'AS DEMANDE.", - "IL TE VAUX MIEUX.", - "BONJOUR, TRANGER!", - "ET TOI... COMMENT TU SAIS QUE JE SUIS UN AVEUGLE?", - "ET TOI TU PARLES COMME LE FILS DE BILL COSBY ET MOI, JE NE T'EMBTE PAS.", - "NON, SI JE NE VOIS PAS.", - "ET MOI, JE NE LE SUIS PAS.", - "OH, BIEN SR! COMME JE NE VOIS PAS ON ME TCHE D'AVEUGLE, N'EST-CE PAS", - "BONJOUR, TRANGER! ET QU'EST-CE QUE TU FAIS EN TRANSYLVANIE?", - "C'EST CORRECT, TRANGER. POUR UNE GROSSE SOMME D'ARGENT, JE TE DONNERAI UNE FAUCILLE, POUR QUAND TU EN AURAS BESOIN.", - "CHUT! JE SUIS UN TRAFICANT DE FAUCILLES, JE DOIS ME CACHER.", - "PARCE QUE TU ME L'AS DIT AVANT, N'EST-CE PAS?", - "MERCI TRANGER. VOIL TA FAUCILLE EN CHANGE. UNE CHOSE QUI SERA TRS PRATIQUE POUR TOI, PLUS TARD... VRAIMENT.", -}, -{ - "", - "COME VA, IGOR?", - "-SEMPRE CHE C' UNA BUONA PARTITA SUCCEDE LO STESSO! BENE, ANDREMO A GUARDARLA AL BAR, COME SEMPRE", - "ADESSO IGOR, ASCOLTA. ANDIAMO A REALIZZARE LA FASE 1 DEL MIO PROGETTO PER CONQUISTARE IL MONDO", - "ATTRARREMO UN FULMINo DELLA TEMPESTA E LO DISMAGNETIZZAREMO CON L'INDIFIBULATORE. LA ELETTRICIT\265 ANDR\265 AL MIO MOSTRO E, GLI DAR\265 VITA!", - "SE TUTTO VA BENE QUESTO SAR\265 SOLTANTO IL PRIMO DI UN'IMMENSO ESERCITO CHE CONQUISTAR\265 IL MONDO PER ME, HA,HA,HA", - "I MOSTRI DISTRUGGERANNO TUTTE LE ARME DI TUTTI GLI ESERCITI DEL MONDO, MENTRE NOI CI RIFURGIAREMO nei miei terreni A GIBRALTAR", - "POI, FAREMO UN GOLPE, E I GOVERNI DEL MONDO NON AVRANNO PER DIFENDERSI, E AVR\220 LE LORO NAZIONI SOTTO I MIEI PIEDI", - "SAR\220 IL PRIMO CATTIVO DELLA STORIA CHE RIESCA!", - "A TE NIENTE, SCIOCCO! ST\220 SPORRENDO LA TRAMA. BENE, TUTTO A POSTO?", - "-\220 IL MOMENTO! -PREMI L'INTERRUTTORE DELLE BATTERIE ALCALINE!", - "- PORCA MISERIA! -CHE COSA NON \220 ANDATA BENE?", - "SEI SICURO DI AVERLO CONTROLLATO BENE? E NO MANCABA NIENTE? ULTIMAMENTE PER I REDDITI NON VEDI UNA MADONNA", - "IMBECILE!, NON HAI CONETTATO L'INDIFIBULATORE! LE VITI SARANO MAGNETIZZATE E ADESSO AVR\265 IL CERVELLO BRUCIATO", - "SEI MORTO, SEI MORTO, COME TI PRENDA..", - "STAI ZITTO! DOMANI CERCHER\220 UN ALTRO CERVELLO E RIPETEREMO L'ESPERIMENTO", - "NO. QUESTA VOLTA NE PORTER\220 UNO DI DONNA, COS\326 SAR\265 NUOVISSIMO, MAI UTILIZZATO. HA, HA HA, CHE BARZELLETA FALLITA", - "E? SONO IL CATTIVO DELLA STORIA, E SONO MASCHILISTA SE VOGLIO, CAPITO? E NON LAMENTARTI UNA ALTRA VOLTA PERCHE MANGERAI LA TUA GOBBA", - "HA,HA,HA. UN ALTRO PRESSO. ADESSO PAGHERAI MOLTO CARO QUESTA OFFESA, LA TUA INTENZIONE DI FINIRE CON ME. -IGOR, AL PENDOLO DELLA MORTE!", - "DIMI, STUPIDO UMANO, COME MAI HAI PENSATO A DISTRUGGERMI?", - "-CHE BELLO!, MI METTEREI A PIANGERE SE NON FOSSE PERCHE MI FA RIDERE", - "HO BISOGNO DELLA TUA RAGAZZA, IL SUO CERVELLO MI AIUTER\265 A CONQUISTARE IL MONDO", - "-SI, HA ! VADO A TOGLIARSILO PER METTEGLIELO AL MIO FRUSKYNSTEIN, E CON LUI DOMINER\220 IL MONDO, HA,HA,HA", - "CHE?! - SEI MORTO, SEI MORTO! TI VADO A...MI HAI FATTO ARRABBIARE. SEI PRONTO PER MORIRE?", - "HA,HA,HA. TU CREDI?", - "SI, VERO? HA,HA,HA", - "VA BENE, PUOI FUMARE LA ULTIMA SIGARETTA, MA SBRIGATI", - "SONO STUFFO, BUTTA GI\265 LA SIGARETTA!", - "E DIMI, QUELLA POZIONE HA L'EFFETTO INVERSO?", - "QUELLO SI VEDR\265 ..", - "BENE, SAR\265 VERO?. IGOR, DAMI IL COMPACT DISC DI UNGHIE GRAFFIANDO UNA LAVAGNA", - "NEANCHE SOGNARLO. LA RAGAZZA RIMANE CON ME, E TU RIMANI LI FINO CHE IL PENDOLO TI TAGLII IN FETTE. HA,HA,HA", - "MA COME SONO CATTIVO, ANDIAMO IGOR, ANDIAMO A FARE LA POZIONE, ANDIAMO A CONQUISTARE IL MONDO", - "ADESSO CHE SUCCEDE?", - "SI, CHE C'E?....LA PARTITA!", - "L'AVEVO DIMENTICATA. PRENDI LA RAGAZZA E ANDIAMO A GUARDARE IL CALCIO. CONQUISTER\220 IL MONDO DOPO", - "GRAZIE AMICO, AVEVO SETE", - "-ARGH! -QUEL CROCIFISSO! -QUEL CROCIFISSO!...", - "QUE BELLO \220 QUEL CROCIFISSO, NON MI ERO ACCORTO", - "LASCIAMI, ST\220 GUARDANDO LA PARTITA", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "Ciao cieco. Come va?.", - "Come sai che sono straniero.", - "Sembri un cieco. Hai gli occhiali come il cieco di Sorrento, parli guardando all'infinito come Stevie Wonder..", - "Bene, scusa. Non sapevo che non vedessi", - "Ma non mi hai appena detto che non sei cieco?.", - "- Ma se non vedi!.", - "Beeeene. Scusa. Allora: Ciao : non vedente", - "Sono John Hacker, st giocando al Drascula. Tu devi proprio essere il tipico personaggio che mi aiuter in cambio di un oggeto. Vero...?", - "Ma... Scusa ciec..- non vedente! .Ma.. . che tipo di mestiere il tuo, di dare falci per soldi, mentre suoni la fisarmonica?.", - "Ah, si. \324 vero. Ciao non vedente....(cieco)", - "Ecco la abbondante quantit di soldi che mi avevi chiesto.", - "Mi raccomando", - "Ciao straniero.", - "E tu... Come sai che sono cieco?", - "E tu parli come il figlio di Bill Cosby e non ti offendo.", - "No, se non vedo.", - "E non lo sono.", - "-Oh, certo!. Come non vedo mi chiamano cieco, no?.", - "-Ciao Straniero! e cosa fai in Transilvania?", - "Corretto straniero. Per una abbondante quantit di soldi, ti dar in cambio una falce, per quando ne avrai bisogno.", - "Shhhhhh. Sono trafficante di falci, devo proprio dissimulare.", - "Perche mi lo hai detto prima, no?", - "Grazie straniero. Ecco la tua falce. Un oggeto che ti sar molto utile pi avanti...... davvero.", -}, -}; - -const char *_textb[][15] = { -{ - "", - "I'M HERE, DRINKING", - "THEY ARE ALL DEAD, THANKS. BURPP...", - "YES, SURE...", - "SHE FEELS ATTRACTED TO UNCLE DESIDERIO", - "EVEN BETTER, UNCLE DESIDERIO'S DEAD BODY", - "MY UNCLE. HE WENT TO CASTLE AND NEVER CAME BACK", - "WELL, HE CAME BACK JUST A LITTLE. IF ONLY VON BRAUN HADN'T SCREWED THINGS UP MY UNCLE WOULD BE DRINKING WITH US NOW", - "NOTHING...", - "WELL, YES !. THAT MEAN MAN HAS TERRIFIED US ALL", - "FROM TIME TO TIME HE COMES DOWN TO THE VILLAGE AND TAKES SOMEONE WITH HIM.", - "A LITTLE WHILE AFTER WE JUST A FEW FOUND BODY PARTS. I THINK HE IS DEALING WITH ORGANS OR SOMETHING LIKE THAT", - "THE ONLY PERSON IN THE VILLAGE WHO KNOWS HOW TO END UP WITH DRASCULA IS A CULTIVATED PERSON", - "HE LIVES IN A LOG-CABIN OUT OF TOWN, EVER SINCE DRASCULA BEAT HIM UP", - "HE IS THE ONLY ONE WHO COULD HELP US WITH DRASCULA, AND HE DOESN'T WANT TO HEAR ABOUT US. HOW DO YOU LIKE THAT?", -}, -{ - "", - "AQUI, BEBIENDO", - "MUERTOS TODOS. GRACIAS. BURRP ", - "SI, NO VEAS... ", - "ESTA POR EL TIO DESIDERIO", - "Y ESTA OTRA, POR EL CADAVER DEL TIO DESIDERIO", - "MI TIO. FUE AL CASTILLO Y NO VOLVIO", - "BUENO, VOLVIO PERO POCO. SI EL VON BRAUN NO HUBIESE METIDO LA PATA MI TIO ESTARIA AQUI BEBIENDO", - "NADA... ", - "\255BUENO, SI! ESE DESALMADO NOS TIENE ATEMORIZADOS A TODOS", - "DE VEZ EN CUANDO BAJA AL PUEBLO Y SE LLEVA A ALGUIEN", - "POCO DESPUES SOLO ENCONTRAMOS UNOS POCOS RESTOS. CREO QUE ESTA TRAFICANDO CON ORGANOS, O ALGO ASI", - "EL UNICO DEL PUEBLO QUE SSABE COMO ACABAR CON DRASCULA TIENE ESTUDIOS", - "DESDE QUE LE DERROTO DRASCULA SE HA APARTADO A UNA CABA\245A EN LAS AFUERAS DEL PUEBLO", - "ES EL UNICO QUE PODRIA AYUDARNOS A ACABAR CON DRASCULA, Y NO QUIERE SABER NADA DE NOSOTROS. \250QUE TE PARECE A TI?", -}, -{ - "", - "HIER, BEI EINEM GUTEN TROPFEN", - "ALLE TOT. VIELEN DANK. RueLPS !", - "YO, STIMMT...", - "DIE HIER IST FueR ONKEL DESIDERIUS", - "UND DIESE HIER FueR DIE LEICHE VON ONKEL DESIDERIUS", - "MEIN ONKEL. ER GING ZUM SCHLOSS UND KAM NICHT ZURueCK", - "NAJA, ER KAM NUR IN RESTEN ZURueCK. WENN VON BRAUN SICH NICHT VERTAN HaeTTE, WueRDE ER JETZT MIT UNS EINEN HEBEN", - "NICHTS...", - "JA STIMMT! DIESER SCHURKE JAGT UNS ALLEN EINE RIESENANGST EIN", - "AB UND ZU GEHT ER RUNTER INS DORF UND HOLT SICH JEMANDEN", - "KURZ DANACH HABEN WIR NUR NOCH RESTE GEFUNDEN, ICH GLAUBE ER HANDELT MIT ORGANEN ODER SO", - "DER EINZIGE, DER MIT DRASCULA FERTIGWERDEN KANN, WAR AN DER UNI ", - "SEITDEM DRASCULA IHN BESIEGT HAT, LEBT ER IN EINER EINSAMEN HueTTE AUSSERHALB DES DORFES", - " ER IST DER EINZIGE, DER DRASCULA ERLEDIGEN KoeNNTE UND WILL NICHTS VON UNS WISSEN. WAS HaeLST DU DAVON ?", -}, -{ - "", - "ICI, EN BUVANT", - "TOUS MORTS. MERCI. BOURRP", - "OUI, VRAIMENT...", - "CELLE-CI POUR L'ONCLE DSIR", - "ET CELLE-L\267 POUR LE CADAVRE D'ONCLE DSIR", - "MON ONCLE EST ALL AU CH\266TEAU ET N'EST PAS ENCORE REVENU", - "BON, IL EST REVENU MAIS POUR PEU DE TEMPS. SI VON BRAUN N'AURAIT FAIT UN IMPAIR, MON ONCLE DSIR SERAIT ICI EN BUVANT", - "RIEN... ", - "EH OUI! CE MALIN NOUS A INTIMIDS \267 TOUS", - "DE FOIS IL DESCEND SUR LE VILLAGE ET ENLEVE QUELQU'UN", - "UN PEU PLUS TARD ON NE TROUVE QUE QUELQUES RESTES. JE PENSE QU'IL FAIT DU TRAFIQUE D'ORGANES, OU QUELQUE CHOSE PAREILLE", - "LE SEUL DU VILLAGE QUI SAIT COMMENT FINIR AVEC DRASCULA IL A DES \220TUDES", - "DEPUIS QUE DRASCULA L'A VAINCU, IL S'EST RETIR\220 DANS UNE CABANE, EN DEHORS DU VILLAGE", - "C'EST LE SEUL QUI POURRAIT NOUS AIDER \267 FINIR AVEC DRASCULA ET LUI NE VEUX RIEN SAVOIR DE NOUS. QU'EN PENSES-TUI?", -}, -{ - "", - "QU\326, BEVENDO", - "MORTI TUTTI. GRAZIE. BURRP", - "SII, CERTO, SICURO..", - "QUESTA PER IL ZIO PEPPINO", - "E QUEST'ALTRA, PER IL CADAVERE DEL ZIO PEPPINO", - "MIO ZIO. FU ANDATO AL CASTELLO, E NON MAI TORNATO", - "EEEHH, TORN\220, MA PER POCO TEMPO. SE IL VON BRAUN NON AVESSE SBAGLIATO, MIO ZIO SAREBBE QU\326 BEVENDO", - "NIENTE..", - "EEH,SI! QUEL MALVAGIO CI HA INTIMORATI", - "A VOLTE SCENDE AL PAESE E QUANDO SE NE VA SI PORTA QUALCUNO", - "UN P\220 DOPO SOLTANTO TROVIAMO QUALQUE RESTO. CREDO CHE TRAFFICA ORGANI O QUALCOSA DEL GENERE", - "L'UNICO DEL PAESE CHE SA COME FINIRE CON DRASCULA \220 UNO CHE HA STUDIATO", - "DA CHE FU SCONFFIGIATO DA DRASCULA SI \220 ALLONTANATO A UNA CAPANNA FUORI DEL PAESE", - "L'UNICO CHE POTREBBE AIUTARCI A VINCERE DRASCULA, E NON VUOLE SAPERE NIENTE DI NOI. COSA PENSI?", -}, -}; - -const char *_textbj[][29] = { -{ - "", - "ARE YOU ALL RIGHT? HEY, COME ON, WAKE UP! CAN YOU HEAR ME? ARE YOU DEAD?", - "NO, MY NAME IS BILLIE JEAN, BUT YOU CAN CALL ME B.J. IT'S SHORTER", - "HA, HA...! THAT WAS A GOOD ONE!", - "WELL, JHONNY. YOU SEE, I WAS HERE JUST READY TO GO TO BED WHEN I HEARD THIS STRONG NOISE DOWN THE CORRIDOR", - "I DIDN'T PAY ATTENTION AT FIRST, BUT AFTER ABOUT TWO HOURS OR SO I COULDN'T SLEEP AND WENT OUT FOR A WALK", - "AS I OPENED THE DOOR I WAS SHOCKED TO FIND YOU THERE, LYING ON THE FLOOR. I THOUGHT YOU WERE DEAD, I SWEAR... HA, HA, SILLY BILLY", - "I WAS GOING TO GIVE YOU THE KISS OF LIFE BUT IT WASN'T NECESSARY BECAUSE YOU STARTED TO TALK", - "YOU SAID SOMETHING ABOUT A SCARECROW. I WAS VERY SCARED, YOU KNOW. IT'S A REAL SHOCK WHEN A DEAD PERSON STARTS TALKING RIGHT?", - "ISN'T THAT RIGHT? WELL, THEN I MANAGED TO BRING YOU TO MY ROOM THE BEST WAY I COULD. I PUT YOU IN BED... AND THAT'S ALL... HA, HA, HA...", - "OH, NO...! IT WASN'T THE HIT, HA, HA. I JUST STEEPED ON YOUR GLASSES BY ACCIDENT", - "YOU REALLY LOOK GOOD WITH THOSE GLASSES. I KNOW HE'S NOT FERNANDO LANCHA, BUT I FIND HIM ATTRACTIVE...", - "YES, YES, I DO... COME ON, HOLD ME AND KISS ME TIGHT", - "OH JHONNY, HONEY, THANKS GOD YOU'RE HERE... THAT DAMNED DRASCULA TIED ME UP TO THE BED AND THEN HE'S GONE DOWNSTAIRS TO SEE THE FOOTBALL GAME", - "YES, IT'S TRUE. PLEASE, SET ME FREE", - "NO, I'M SORRY. I USED THEM ALL IN THE TOWER WHEN I WAS TRYING TO LIBERATE WHILE YOU LET ME DOWN", - "JOHNNY, IS THAT YOU? OH, GOD, GREAT! I KNEW YOU'D COME!", - "YOU DON'T EVEN KNOW HOW MUCH THAT EVIL DRASCULA HAS MADE ME SUFFER", - "FIRSTLY HE BROUGHT ME FLYING OVER HER AND THEN PUT ME IN THIS DISGUSTING ROOM WITHOUT EVEN A MIRROR OR ANYTHING", - "I'M TELLING YOU! AND THE WORSE PART IS THAT HE DIDN'T EVEN APOLOGIZE, NOT EVEN ONCE", - "JHONNY HONEY, WHERE ARE YOU?", - "I'M READY TO LEAVE DEAR", - "WAIT, I'M GOING TO TAKE A LOOK... NO DARLING, I'M SORRY", - "THERE YOU GO...", - "\"DEAR JOHNNY\"", - "I'LL NEVER FORGET YOU BUT I'VE REALIZED THAT THIS JUST COULDN'T WORK OUT RIGHT. TO BE HONEST, I'LL TELL YOU THAT THERE IS ANOTHER MAN. HE'S TALLER, STRONGER", - "AND HE HAS ALSO RESCUED ME FROM DRASCULA. HE HAS ASKED ME TO MARRY HIM, AND I HAVE ACCEPTED", - "BYE JHONNY. PLEASE DON'T TRY TO FIND SOME KIND OF EXPLANATION. YOU KNOW LOVE IS BLIND AND HAS ITS OWN WAYS", - "I HOPE THERE WON'T BE HARD FEELINGS BETWEEN US. REMEMBER THAT I STILL LOVE YOU, BUT ONLY AS A FRIEND", -}, -{ - "", - "\250ESTA USTED BIEN? OIGA, DESPIERTE. \250ME OYE? \250ESTA USTED MUERTO?", - "NO, MI NOMBRE ES BILLIE JEAN, PERO PUEDES LLAMARME B.J. ES MAS CORTO", - "\255JI, JI! \255QUE BUENO!", - "PUES VERAS JOHNY, YO ESTABA AQUI, DISPUESTA A ACOSTARME, CUANDO OI UN FUERTE GOLPE EN EL PASILLO", - "AL PRINCIPIO NO LE DI MUCHA IMPORTANCIA, PERO A LAS DOS HORAS MAS O MENOS DESCUBRI QUE NO PODIA DORMIR Y DECIDI SALIR A DAR UN PASEO", - "Y CUAL NO SERIA MI SORPRESA CUANDO ABRI LA PUERTA Y TE ENCONTRE AHI, EN EL SUELO TIRADO. TE LO JURO QUE PENSE QUE HABIAS MUERTO, JE, JE, TONTA DE MI", - "TE FUI A HACER EL BOCA A BOCA, PERO NO FUE NECESARIO PORQUE EMPEZASTE A HABLAR", - "DECIAS NO SE QUE DE UN ESPANTAPAJAROS. YO ME LLEVE UN SUSTO MUY GORDO, PORQUE CUANDO UN MUERTO SE PONE A HABLAR ES UNA IMPRESION MUY FUERTE, \250NO CREES?", - "\250VERDAD QUE SI? BUENO, PUES COMO PUDE, CARGUE CONTIGO Y TE TRAJE A MI HABITACION. TE PUSE SOBRE LA CAMA... Y ESO ES TODO. JI, JI,JI", - "OH, NO HA SIDO EL GOLPE, JI, JI. ES QUE SIN QUERER PISE TUS GAFAS", - "\255HAY QUE VER QUE BIEN LE SIENTAN LAS GAFAS! YA SE QUE NO ES FERNANDO LANCHA, PERO TIENE UN NO SE QUE QUE QUE SE YO", - "SI, SI, QUIERO... VAMOS, ABRAZAME FUERTE, BESAME MUCHO...", - "OH JOHNY, CARI\245O, MENOS MAL QUE HAS VENIDO. ESE DESALMADO DE DRASCULA ME HA ATADO A LA CAMA Y LUEGO SE HA IDO ABAJO A VER EL PARTIDO", - "SI, ES VERDAD. LIBERAME ", - "NO, LO SIENTO. GASTE TODAS EN LA MAZMORRA INTENTANDO LIBERARME MIENTRAS TU ME DEJABAS TIRADA", - "JOHNY \250ERES TU? \255QUE ALEGRIA! \255SABIA QUE VENDRIAS!", - "NO SABES CUANTO ME HA HECHO SUFRIR ESE DESALMADO DE DRASCULA", - "PRIMERO ME TRAJO VOLANDO HASTA AQUI Y LUEGO ME ENCERRO EN ESTE CUARTUCHO, SIN ESPEJO NI NADA", - "COMO LO OYES. Y LO PEOR ES QUE NO PIDIO PERDON NI UNA SOLA VEZ", - "JOHNY, QUERIDO. \250DONDE ESTAS?", - "ESTOY LISTA PARA QUE ME SAQUES DE AQUI", - "ESPERA QUE VOY A MIRAR... NO CARI\245O, LO SIENTO", - "TOMA...", - "\"QUERIDO JOHNY:", - "NUNCA PODRE OLVIDARTE, PERO ME HE DADO CUENTA DE QUE LO NUESTRO NO FUNCIONARIA. VOY A SER SINCERA CONTIGO: HAY OTRO HOMBRE; MAS ALTO, MAS FUERTE...", - "Y ADEMAS ME HA RESCATADO DE LAS MANOS DE DRASCULA. ME HA PEDIDO EN MATRIMONIO, Y YO HE ACEPTADO", - "ADIOS, JOHNY. NO INTENTES DARLE UNA EXPLICACION, PORQUE EL AMOR ES CIEGO Y NO ATIENDE A RAZONES", - "ESPERO QUE NO ME GUARDES RENCOR, Y RECUERDA QUE TE SIGO QUERIENDO, AUNQUE SOLO COMO AMIGO\"", -}, -{ - "", - "HALLO, ALLES KLAR ?HEY, WACHEN SIE AUF. HoeREN SIE MICH ? SIND SIE TOT ?", - "NEIN, ICH HEISSE BILLIE JEAN., ABER DU KANNST MICH B.J. NENNEN, DAS IST KueRZER", - "HI,HI! SUPERGUT !", - "JA STELL DIR VOR, HEINZ, ICH WOLLTE MICH HIER GERADE HINLEGEN, ALS ICH EINEN LAUTEN KNALL IM FLUR HoeRTE", - "ANFANGS HAB ICH NICHT SO DRAUF GEACHTET, ABER NACHDEM ICH 2 STUNDEN LANG NICHT SCHLAFEN KONNTE, GING ICH RUNTER, UM SPAZIERENZUGEHEN", - "ICH WAR NATueRLICH BAFF, ALS ICH DICH VOR der tuer LIEGEN SAH. ICH HABE ECHT GEDACHT,DASS DU TOT BIST, HEHE, WIE bloed" - "ICH WOLLTE GERADE MUND-ZU-MUND BEATMUNG MACHEN, ABER DANN FINGST DU JA AN ZU REDEN", - "DU FASELTEST WAS VON NER VOGELSCHEUCHE UND ICH Hatte ganz schoen schiss,WEIL sprechende tote schon echt UNHEIMLICH sind?", - "NICHT WAHR ?NAJA,ICH HABE DICH DANN AUFGEHOBEN UND IN MEIN ZIMMER GETRAGEN UND AUF MEIN BETT GELEGT.... WEITER NICHTS. HI,HI,HI", - "ACH NEIN, ES WAR NICHT DIE BEULE, HIHI, ICH BIN VERSEHENTLICH AUF DEINE BRILLE GETRETEN ", - "MAN MUSS SICH ECHT MAL ANGUCKEN, WIE GUT IHM DIE BRILLE STEHT. ER IST ZWAR NICHT DER MARTINI-MANN, ABER ER HAT WAS WEISS ICH WAS", - "JA, JA, ICH WILL. KOMM NIMM MICH UND KueSS MICH...", - "OH HEINZ, LIEBLING, GUT DASS DU DA BIST. DIESER WueSTLING VON DRASCULA HAT MICH ANS BETT GEFESSELT UND IST DANN RUNTER UM SICH DAS SPIEL ANZUSEHEN", - "JA, WIRKLICH. BEFREIE MICH", - "NEIN, TUT MIR LEID. ICH HAB ALLE BEIM VERSUCH, AUS DEM VERLIES AUSZUBRECHEN, AUFGEBRAUCHT", - "HEINZ, BIST DU ES ? WIE TOLL ! ICH WUSSTE, DASS DU KOMMEN WueRDEST !", - "DU AHNST JA NICHT, WIE SEHR ICH WEGEN DIESEM UNGEHEUER VON DRASCULA GELITTEN HABE", - "ZUERST IST ER MIT MIR HIERHER GEFLOGEN UND DANN HAT ER MICH IN DIESES LOCH GESPERRT, OHNE SPIEGEL UND GAR NICHTS", - "WIE ICHS GESAGT HABE. DAS SCHLIMMSTE IST,DASS ER SICH KEIN EINZIGES MAL ENTSCHULDIGT HAT.", - "HEINZ, GELIEBTER, WO BIST DU ?", - "ICH BIN BEREIT, VON DIR GERETTET ZU WERDEN", - "WARTE, ICH GUCK MAL...NEIN, SCHATZ, TUT MIR LEID", - "HIER NIMM...", - "LIEBER HEINZ !", - "ICH WERDE DICH NIE VERGESSEN, aber das mit uns funktioniert nicht.ICH gebs zu : ES GIBT EINEN ANDERN. GRoeSSER,STaeRKER...", - "UND AUSSERDEM HAT ER MICH AUS DRASCULAS KLAUEN BEFREIT UND UM MEINE HAND ANGEHALTEN,UND ICH HABE JA GESAGT", - "LEB WOHL,HEINZ. VERSUCH NICHT EINE ERKLaeRUNG ZU FINDEN, DENN DIE LIEBE IST BLIND UND KENNT KEINE VERNUNFT", - "DU BIST MIR HOFFENTLICH NICHT BoeSE. DENK IMMER DARAN DASS ICH DICH IMMER NOCH LIEBE, WENN AUCH NUR ALS FREUND", -}, -{ - "", - "VOUS ALLEZ BIEN? ALLEZ, REVEILLEZ-VOUS! VOUS M'ENTENDEZ? VOUS \322TES MORT?", - "NON, MON NOM EST BILLIE JEAN, MAIS TU PEUX M'APPELLER B.J., C'EST PLUS COURT", - "HI! HI! -C'EST BON!", - "EN VRIT JOHNY, J'TAIS L\267, PR\322TE \267 ME COUCHER, ET J'AI ENTENDU UN FORT COUP DANS LE COULOIR", - "AU DBUT JE N'Y AI PAS DONN D'IMPORTANCE, MAIS APR\324S JE ME SUIS RENDUE COMPTE QUE NE POUVAIS PAS M'ENDORMIR ET SUIS SORTIE FAIRE UNE PROMENADE", - "ET \267 MON GRAN TONNEMENT, QUAND J'AI OUVERT LA PORTE, JE T'AI TROUV L\267, PAR TERRE. J'TAIS SUR LE POINT DE PENSER QUE TU AVAIS MORT, HE!, QUE JE SUIS B\322TE!", - "J'ALLAIS TE FAIRE LE BOUCHE-\267-BOUCHE MAIS IL N'A T PAS NCESSAIRE PUISQUE TU AS COMMENC \267 PARLER", - "TU DISAIS \267 SAVOIR QUOI D'UN POUVANTAIL. CELA M'A FAIT UNE GRANDE PEUR, PARCE QUE QUAND UN MORT SE MET \267 PARLER L'IMPRESSION EST TR\324S FORTE, NE CROIS-TU PAS?", - "C'EST VRAI, NON? ENFIN. JE ME SUIS DBROUILLE POUR TE PRENDRE SUR MOI, T'EMMENER DANS MA CHAMBRE ET T'INSTALLER SUR LE LIT... ET VOIL\267 TOUT. HI! HI! HI!", - "HO! CE N'EST PAS \267 CAUSE DU COUP, HI! HI! CE QUE J'AI MARCHE SUR TES LUNETTES PAR ACCIDENT", - "\220VIDEMMENT LES LUNETTES LUI FONT DU BIEN! JE SAIS BIEN QUIL N'EST PAS FERNANDO LANCHA, MAIS IL A UN AIR QU'ALLEZ DONC SAVOIR", - "OUI, OUI, JE VEUX... VAS-Y, EMBRASSE-MOI FORT, EMBRASSE-MOI BEAUCOUP...", - "OH,JOHNY!, MON AMOUR! HEUREUSEMENT QUE TU ES VENU. CE M\220CHANT DRASCULA M'A ATTACH\220 AU LIT ET APR\324S IL EST PARTI EN BAS VOIR LE MATCH", - "OUI, C'EST VRAI, LIB\324RE-MOI", - "NON, SUIS D\220SOL\220E. JE LES AI TOUTES UTILIS\220ES, DANS LE CACHOT, EN T\266CHANT DE ME LIB\220RER ALORS QUE TOI TU M'ABANDONNAIS", - "JOHNY, C'EST TOI? -QUELLE JOIE! -JE SAVAIS QUE TU VIENDRAIS!", - "TU NE PEUX PAS SAVOIR COMBIEN M'A FAIT SOUFFRIR CE M\220CHANT DRASCULA", - "D'ABORD IL M'EMMEN\220 EN VOLANT JUSQU'ICI ET APR\324S IL M'ENFERM\220E DANS CE TAUDIS, SANS MIROIR NI RIEN D'AUTRE", - "COMME TU L'ENTENDS. ET LE PIRE C'EST QUIL NE M'A PAS DEMAND\220 PARDON N'UNE SEULE FOIS ", - "JOHNY, MON CH\220RI, O\353 EST-CE QUE TU ES?", - "JE SUIS PR\322TE POUR QUE TU M'EN SORTES D'ICI", - "ATTEND, JE VAIS REGARDER... NON CH\220RI, JE REGRETTE", - "TIENS...", - "\"CHER JOHNY", - "JAMAIS JE T'OUBLIERAI, MAIS JE ME SUIS APER\200UE QUE NOTRE AFFAIRE NE POUVAIT PAS MARCHER. JE VAIS \322TRE SINC\324RE AVEC TOI: IL Y A UN AUTRE HOMME, PLUS GRAND...", - "ET ENCORE IL M'A LIB\220R\220 DES MAINS DE DRASCULA. IL M'A DEMAND\220 EN MARIAGE, ET MOI J'AI ACCEPT\220", - "AU REVOIR, JOHNY. N'Y CHERCHES PAS UNE EXPLICATION, L'AMOUR EST AVEUGLE ET N'\220COUTE PAS DES RAISONS", - "J'ESP\324RE QUE TU SERAS SANS RANCUNE, ET N'OUBLIES PAS QUE JE T'AIME ENCORE, MAIS EN AMI SEULEMENT\"", -}, -{ - "", - "ST\265 BENE? SENTA, PUO SENTIRMI? SI \220 MORTO?", - "NO, IL MIO NOME BILLIE JEAN, MA PUOI CHIAMARMI B.J. PI \351 BREVE", - "HI,HI!- CHE BUONO!", - "NON SO JOHNY, ERO QU\326, STAVO PER ADDORMENTARMI, QUANDO HO SENTITO UN FORTE RUMORE NEL CORRIDOIO", - "PRIMA NON GLI HO DATTO IMPORTANZA, MA DUE ORE DOPO HO SCOPERTO CHE NON RIUSCIVO A ADDORMENTARMI E SONO uscita A FARE QUATTRO PASSI", - "E FIGURATI LA SORPRESA QUANDO HO APERTO LA PORTA E TI HO TROVATO PER TERRA. TI GIURO, HO PENSATO CH'ERI MORTO..., MA COME SONO SCIOCCA", - "VOLEVO FARTI IL BOCCA A BOCCA, MA NON C'ERA BISOGNO PERCHE SUBITO HAI COMINCIATO A PARLARE", - "HAI DETTO NON SO CHE DI UN SPAVENTAPASSERI. CHE COLPO.....!, PERCHE QUANDO UN MORTO SI METTE A PARLARE FA UN COLPO GRANDISSIMO!", - "VERO DI SI? NON SO COME SONO RIUSCITA, TI HO TRASPORTATO ALLA MIA CAMERA, TI HO MESSO SUL MIO LETTO E.... NIENTE PI\351 .", - "NO, NON \220 STATA LA BOTTA, HI, HI. \220 PERCHE ... HO PESTATO I TUOI OCCHIALI", - "MAMMA MIA MA COM'\220 BELLO CON GLI OCCHIALI! SO CHE NON \220 FERNANDO LANCHA, MA HA QUALCOSA CHE MI PIACE MOLTISSIMO", - "SI,SI, VOGLIO... ABBRACIAMI FORTE, BACIAMI MOLTO..", - "OH JOHNY, CARO, MENO MALE CHE SEI VENUTO. QUEL MALVAGIO, DRASCULA, MI HA LEGATO AL LETTO E POI SE NE \220 ANDATO A GUARDARE LA PARTITA", - "SI, \220 VERO, LIBERAMI", - "NO, MI DISPIACE. HO UTILIZZATO TUTTE IN CARCERE PROBANDO LIBERARMI QUANDO TU MI AVEVI LASCIATA", - "JOHNY, SEI TU? - BENISSIMO. LO SAPEVO ", - "NON TI FIGURI QUANTO MI HA FATTO SOFFRIRE DRASCULA", - "PRIMA MI HA PORTATO VOLANDO FINO QUA E POI MI HA RICHIUSA IN QUESTA CAMERACCIA CHE NON HA N\220 UNO SPECCHIO", - "COME HAI SENTITO. E LO PEGLIORE: N\220 UNA VOLTA SI \220 SCUSATO", - "JOHNY, CARO. DOVE SEI?", - "SONO PRONTA, FAMI USCIRE DA QU\326 ", - "ASPETTA, VADO A GUARDARE... NO CARO, MI DISPIACE", - "PRENDI..", - "\"CARO JOHNY:", - "MAI POTR\220 DIMENTICARTI, MA NON SAREMO MAI FELICI INSIEME. SAR\220 SINCERA CON TE : C'\220 NE UN ALTRO; PI\351 ALTO, PI\351 FORTE..", - "ANZI MI HA LIBERATO DA DRASCULA. MI HA CHIESTO LA MANO E HO DETTO DI SI", - "ADIO JOHNY. NON CERCARE UNA SPIEGAZIONE, PERCHE L'AMORE \220 CIECO.", - "SPERO NON MI ODII, E RICORDA CHE ANCORA TI VOGLIO BENE, SEBBENE SOLO COME UN AMICO\"", -}, -}; - - -const char *_texte[][24] = { -{ - "", - "YOU... HEY YOU!", - "DON'T GIVE ME THAT CRAP ABOUT A DEAD BODY OK?", - "I'M ALIVE. IT'S JUST THAT I'M STARVING", - "WELL, YOU SEE. I WAS THE DRUNKARD OF THE VILLAGE, JUST KEEPING UP WITH THE FAMILY TRADITION, YOU KNOW? ONE NIGHT DRASCULA KIDNAPPED ME TO TAKE MY ORGANS AWAY", - "SINCE ALCOHOL STILL KEEPS ME QUITE YOUNG, I'M HERE LIKE A SCRAP YARD. EVERYTIME HE NEEDS SOMETHING FOR THE MONSTER HE IS MAKING, HE COMES AND TAKES IT FROM ME", - "IT HURT AT FIRST, BUT I DON'T CARE ANYMORE", - "I DON'T KNOW. I GUESS IT'S HIS GRADUATE PROJECT", - "I'M DESIDERIO, AND I CAN HELP YOU IN ANYTHING YOU NEED", - "THE TRUTH IS THAT I DON'T REALLY FEEL LIKE IT, BUT THANKS VERY MUCH ANYWAY SIR", - "YEAH, IT'S YOU", - "WHY DO ALL ADVENTURE GAMES END UP WITH A SUNRISE OR A SUNSET?", - "DO ALL THESE NAMES BELONG TO THE CREATORS OF THE GAME?", - "AREN'T THEY ASHAMED TO BE SEEN BY EVERYBODY?", - "JESUS, THAT EMILIO DE PAZ IS EVERYWHERE!!", - "REALLY?", - "YES", - "WELL, DON'T MAKE A FUSS ABOUT IT", - "HEY WEREWOLF, BY THE WAY...", - "DIDN'T YOU FALL OFF A WINDOW AND GOT BADLY HURT", - "IF AT LEAST IT WASN'T ALWAYS THE SAME ONES...", - "HE'S BEEN OUT FOUR TIMES ALREADY", - "I'D LIKE TO BE A MODEL", - "ALL RIGHT, AND WHAT ARE YOU GOING TO DO?", -}, -{ - "", - "EO, USTED", - "\255QUE MUERTO NI OCHO CUARTOS!", - "ESTOY VIVO, LO QUE PASA ES QUE YO PASO HAMBRE, \250SABE USTED? ", - "PUES VERA, SE\245OR. YO ERA EL BORRACHO DEL PUEBLO, DIGNO SUCESOR DE UNA FAMILIA DE ILUSTRES BORRACHUZOS, Y UNA NOCHE DRASCULA ME SECUESTRO PARA ROBARME LOS ORGANOS", - "RESULTA QUE COMO ME CONSERVO EN ALCOHOL, ME TIENE AQUI EN PLAN DESSGUACE. CADA VEZ QUE NECESITA ALGO PARA EL MONSTRUO QUE ESTA CREANDO VIENE Y ME LO COGE", - "AL PRINCIPIO ME DOLIA, NO CREA, PERO YA ME DA IGUAL", - "NO SE, SERA SU PROYECTO DE FIN DE CARRERA", - "MI NOMBRE ES DESIDERIO, PARA SERVIRLE A USTED", - "PUES LA VERDAD ES QUE NO TENGO MUCHA GANA, PERO MUCHAS GRACIAS DE TODAS MANERAS, SE\245OR", - "SI, TU MISMO", - "\250POR QUE TODOS LOS JUEGOS DE AVENTURAS TERMINAN CON UN AMANECER O UNA PUESTA DE SOL? ", - "\250Y TODOS ESTOS NOMBRES SON DE LOS QUE HAN HECHO EL JUEGO?", - "\250Y NO LES DA VERG\232ENZA SALIR Y QUE LOS VEA TODO EL MUNDO?", - "JOLIN, NO HACE MAS QUE SALIR \"EMILIO DE PAZ\" ", - "\250DE VERDAD?", - "SI", - "PUES NO ES PARA TANTO", - "POR CIERTO HOMBRE LOBO...", - "... \250NO CAISTE POR UNA VENTANA Y TE HICISTE POLVO?", - "SI AL MENOS NO FUESEN SIEMPRE LOS MISMOS", - "ESE YA HA SALIDO CUATRO VECES", - "ME GUSTARIA SER MODELO", - "YA, \250Y TU QUE VAS A HACER?", -}, -{ - "", - "EJ, SIE DAA", - "DU BIST WOHL BESOFFEN ODER WAS ? !", - "ICH BIN LEBENDIG, ABER ICH HABE HUNGER, WISSEN SIE ?", - "TJA,ICH WAR DER DORFSaeUFER, STOLZER abkomme EINER DORFSaeUFERsippe UND EINES NACHTS holte mich DRASCULA, UM MIR DIE ORGANE ZU KLAUEN", - "WEIL ICH MICH IN ALKOHOL gut HALTE BIN ICH SEIN ERSATZTEILLAGER. IMMER WENN ER WAS FueR SEIN MONSTERCHEN BRAUCHT, BEDIENT ER SICH BEI MIR", - "AM ANFANG TAT DAS HoeLLISCH WEH, ABER JETZT MERK ICH SCHON NICHTS MEHR", - "KEINE AHNUNG, ES WIRD WOHL SEINE DIPLOMARBEIT SEIN", - "ICH HEISSE DESIDERIUS UND STEHE ZU IHREN DIENSTEN", - "NAJA, EIGENTLICH HABE ICH KEINE GROSSE LUST ABER VIELEN DANK JEDENFALLS, MEIN HERR", - "JA,NUR ZU", - "WARUM HoeREN ALLE SPIELE MIT SONNENAUFGANG ODER SONNENUNTERGANG AUF ?", - "UND SIE HABEN DIE NAMEN VON DEN MACHERN DIESES SPIELS BENUTZT ?", - "UND SIE SCHaeMEN SICH NICHT SICH ALLER WELT ZU OFFENBAREN ?", - "SCHEIBENKLEISTER. SCHON WIEDER DER PROGRAMMIERER", - "WIRKLICH ?", - "JA", - "SO SCHLIMM IST ES AUCH WIEDER NICHT", - "APROPOS WERWOLF....", - "....BIST DU NICHT AUS EINEM FENSTER GEFALLEN UND ZU STAUB GEWORDEN ?", - "WENN ES WENIGSTENS NICHT IMMER DIESELBEN WaeREN", - "DER IST SCHON 4 MAL AUFGETAUCHT", - "ICH WaeRE GERN FOTOMODELL", - "KLAR, UND WAS WILLST DU SPaeTER MAL MACHEN ?", -}, -{ - "", - "OH\220! VOUS!", - "QUEL MORT NI QUELLE HISTOIRE!", - "JE SUIS VIVANT. C'EST QUE J'AI FAIM, VOUS SAVEZ? ", - "J'TAIS L'IVROGNE DU VILLAGE, LE DIGNE REPRSENTANT D'UN FAMILLE D'ILLUSTRES SO\352LARDS, ET DRASCULA M'A SQUESTR UNE NUIT POUR ME VOLER LES ORGANES", - "COMME JE ME CONSERVE EN ALCOOL, IL ME TIENS ICI EN PLAN DBALLAGE. \267 CHAQUE FOIS QU'IL A BESOIN DE QUELQUE CHOSE POUR SON MONSTRE, IL LE PRENDRE", - "AU DBUT A ME FAISAIT MAL, MAIS JE M'EN FICHE DJ\267", - "JE NE SAIS PAS, MAIS CE SERA SON PROJET FIN D'TUDES", - "MON NOM EST DSIR, POUR VOUS SERVIR", - "VRAIMENT JE N'AI PAS UNE ENVIE FOLLE, MAIS MERCI QUAND M\322ME, MONSIEUR", - "OUI, TOI M\322ME", - "POURQUOI TOUS LES JEUX D'AVENTURES FINISSENT AVEC UNE AUBE OU UN COUCHER DU SOLEIL? ", - "ET VOIL\267 LES NOMS DE TOUS QUI ON FAIT LE JEU?", - "ET N'ONT-ILS PAS LA HONTE DE SE MONTRER ET QUE TOUT LE MONDE LES VOIT?", - "AH ZUT! IL NE FAIT QUE SORTIR \"EMILIO DE PAZ\" ", - "C'EST VRAI", - "OUI", - "EH BIEN, IL NE FAUT PAS EXAG\220RER", - "EN FAIT HOMME-LOUP...", - "...N'EST-TU PAS TOMB\220 D'UNE FEN\322TRE EN TE BR\220SILLANT?", - "SI DU MOINS N'\220TAIENT PAS TOUJOURS LES M\322MES...", - "CELUI-L\267 EST D\220J\267 SORTI QUATRE FOIS", - "J'AIMERAIS \322TRE MANNEQUIN", - "PARFAITEMENT. ET TOI, QUE VAS-TU FAIRE?", -}, -{ - "", - "EO, LEI", - "MA CHE DICI!", - "SONO VIVO, MA HO SEMPRE MOLTA FAME, SA LEI?", - "IO ERO IL BEONE DEL PAESE, DEGNO SUCCESSORE DI UNA FAMIGLIA DI ILLUSTRI BEONI, E UNA NOTTE DRASCULA MI SEQUESTR\220 PER RUBARMI GLI ORGANI", - "mi utilizza COME UNO SCASSO, OGNI VOLTA CHE HA BISOGNO DI QUALCOSA PER IL MOSTRO CHE ST\265 CREANDO VIENE QUA E MI LO toglia", - "AL INIZIO MI FACEVA MALE, MA ORA NON FA NIENTE", - "NON SO, SAR\265 LA SUA TESINA DI FINE DI LAUREA", - "IL MIO NOME PEPPINO, PER SERVIRGLI", - "LA VERIT\265 CHE NON HO MOLTA VOGLIA, COMUNQUE GRAZIE MILE, SIGNORE", - "SI, PROPRIO TU", - "PER CHE TUTTI I VIDEO-GIOCHI D' AVVENTURE FINISCONO CON UN'ALBEGGIARE O UN TRAMONTO?", - "E TUTTI QUESTI NOMI SONO DI CHI HANNO FATTO IL GIOCO?", - "E NON SI VERGOGNANO DI USCIRE ED ESSERE VISTI DA TUTTI QUANTI?", - "UFFA, SOLTANTO ESCI \"EMILIO DE PAZ\"", - "DAVVERO?", - "SI", - "NON \220 PER METTERSI COS\326 ", - "CERTO LUPO-MANNARO..", - "... MA NON SEI CADUTO DA UNA FINESTRA E TI HAI FATTO MALE?", - "SE PER UNA VOLTA NON FOSSENO SEMPRE GLI STESSI", - "QUELLO \220 GIA USCITO QUATRO VOLTE", - "MI PIACEREBBE ESSERE TOP MODEL", - "SI, E TU, COSA VAI A FARE?", -}, -}; - - -const char *_texti[][33] = { -{ - "", - "MASTER, I THINK THIS IS NOT WORKING", - "I AM POSITIVE, MASTER", - "I'M SORRY MASTER", - "ARE YOU GOING TO BRING HERE ANOTHER CRAZY SCIENTIST? I'LL TELL YOU THAT THE LABORATORY IS ALREADY PACKED UP, AND BESIDES, THEY'RE ALL OUT OF DATE", - "HUSH MASTER, THE FEMINIST COULD HEAR YOU", - "DAMNED IT!", - "I DIDN'T EXPECT YOU SO SOON, MASTER", - "QUITE BAD MASTER. THERE MUST BE SOME PROBLEMS WITH THE SATELLITE AND I JUST CAN'T RECEIVE ANYTHING. BESIDES THERE ARE SOME INTERFERENCES BECAUSE OF THE STORM", - "WHAT DO I KNOW, MASTER?", - "YES, MY MASTER", - "MASTER", - "DO YOU KNOW WHAT TIME IS IT?", - "WHAT? OH, THAT SCARED ME!. YOU ARE THE \"NIGHT-CLEANING GUY\", RIGHT?", - "I'M IGOR, THE VALET. YOU CAN START WITH THE BALL ROOM. THERE'S BEEN A SUPER NATURAL ORGY YESTERDAY AND IT LOOKS LIKE SHIT", - "IF YOU NEED ANYTHING, JUST BUY IT", - "IT'S THE TAX RETURN APPLICATION FORM, CAN'T YOU SEE IT?", - "NEITHER DO I. FIRST OF ALL THE NUMBERS ARE VERY SMALL AND ALSO I CAN'T SEE MUCH AT THIS DISTANCE.", - "NO WAY! THEY MAKE ME LOOK UGLY", - "OH, WELL. IT'S JUST LIKE A CRAZY PARTY THAT THE MASTER ORGANIZES WITH HIS FRIENDS EACH TIME SOME IDIOT COMES ALONG TRYING TO KILL HIM", - "THEY TAKE HIS EYES OUT. THEN, POUR SOME LEMON JUICE SO THAT IT ITCHES TO DEATH, AND THEN...", - "NO", - "WHAT DO YOU MEAN WHY NOT? DO YOU KNOW WHAT TIME IT IS?", - "YES, IT'S WINTER", - "SEE YOU LATER", - "DON'T EVEN THINK ABOUT IT!", - "WELL, THAT'S ENOUGH FOR TODAY. I'M GOING TO HAVE SUPPER", - "MAN, I ALWAYS FORGET TO LOCK IT, RIGHT?", - "THE HELL WITH IT!", - "WHAT? OH, YOU SCARED ME MASTER, I THOUGHT YOU WERE ASLEEP", - "OH, BY THE WAY, I TOOK THE LIVING-ROOM KEYS SO THAT YOU CAN WATCH THE EARLY MORNING CARTOONS WITHOUT WAKING ME UP", - "YOU'VE GOT ANOTHER COLD MASTER? DAMN IT! I TOLD YOU TO GET SOME HEATING IN HERE...", - "ALL RIGHT, JUST TAKE YOUR ASPIRIN AND GO TO BED TO SWEAT FOR A WHILE. GOOD NIGHT", -}, -{ - "", - "MAESTRO, CREO QUE ESTO NO RULA", - "ESTOY SEGURISIMO, MAESTRO...", - "LO SIENTO, MAESTRO", - "\250VA A TRAER OTRO DE CIENTIFICO LOCO? LE ADVIERTO QUE TENEMOS EL LABORATORIO LLENO Y ESTAN TODOS CADUCADOS", - "CALLE, MAESTRO, QUE COMO LE OIGAN LAS FEMINISTAS", - "HAY QUE JOROBARSE", - "\255MAESTRO! \255NO LE ESPERABA TAN PRONTO!", - "MAL MAESTRO, DEBE HABER PROBLEMAS CON EL SATELITE Y NO CONSIGO SINTONIZAR LA IMAGEN. ADEMAS LA TORMENTA PRODUCE INTERFERENCIAS", - "\250Y A MI QUE ME CUENTA, MAESTRO?", - "SI, MAESTRO", - "MAESTRO", - "\250SABE LA HORA QUE ES?", - "\250EH? \255AH, QUE SUSTO ME HAS DADO! TU ERES EL DE \"LIMPIEZA NOCTURNA\"\250NO?", - "YO SOY IGOR, EL MAYORDOMO. PUEDES EMPEZAR POR EL SALON DE BAILE. AYER HUBO ORGIA SOBRENATURAL Y ESTA HECHO UNA MIERDA", - "SI NECESITAS ALGO, LO COMPRAS", - "LA DECLARACION DE LA RENTA \250ES QUE NO LO VES?", - "PUES YO TAMPOCO, PORQUE ENTRE QUE LOS NUMEROS SON MUY CHICOS, Y YO QUE NO VEO BIEN DE LEJOS...", - "\255NI HABLAR! ME HACEN PARECER FEO", - "BAH, ES UN FESTORRO QUE SE MONTA EL MAESTRO CON SUS COLEGAS CADA VEZ QUE LLEGA ALGUN IMBECIL QUERIENDO ACABAR CON EL", - "PRIMERO LE SACAN LOS OJOS; LUEGO LE ECHAN ZUMO DE LIMON PARA QUE LE ESCUEZA; DESPUES...", - "NO", - "\250COMO QUE POR QUE NO? \250TU HAS VISTO LA HORA QUE ES?", - "EN INVIERNO, SI", - "HASTA LUEGO", - "\255NI SE TE OCURRA!", - "BUENO, POR HOY YA VALE. ME VOY A CENAR", - "\255Y QUE SIEMPRE SE ME OLVIDA CERRAR CON LLAVE!", - "\255HAY QUE JOROBARSE!", - "\250EH? \255AH! QUE SUSTO ME HA DADO, MAESTRO. CREIA QUE ESTABA DURMIENDO", - "AH, POR CIERTO, TOME LAS LLAVES DE LA SALA DE ESTAR Y ASI NO ME MOLESTA MA\245ANA TEMPRANO SI QUIERE VER LOS DIBUJOS", - "\250QUE, YA SE HA RESFRIADO OTRA VEZ, MAESTRO? HAY QUE JOROBARSE. SI SE LO TENGO DICHO, QUE PONGA CALEFACCION... ", - "BUENO, TOMESE UNA PASTILLA DE ACIDOACETIL SALICILICO Y HALA, A SUDAR. BUENAS NOCHES", -}, -{ - "", - "MEISTER, ICH GLAUBE, DAS KLAPPT NICHT", - "ICH BIN ABSOLUT SICHER, MEISTER....", - "TUT MIR LEID, MEISTER", - "NOCH SO EINEN VERRueCKTEN WISSENSCHAFTLER ? ABER DAS LABOR IST DOCH VOLL MIT IHNEN UND ALLE SIND ueBER DEM VERFALLSDATUM", - "SEIEN SIE STILL MEISTER. WENN DAS DIE FEMINISTINNEN HoeREN", - "GRueNSPAN UND ENTENDRECK", - "MEISTER! ICH HABE SIE NOCH GAR NICHT ERWARTET !", - "SCHLECHT, MEISTER. ES GIBT WOHL PROBLEME MIT DER SCHueSSEL UND ICH BEKOMME DAS BILD EINFACH NICHT KLAR. UND DANN DAS GEWITTER !", - "UND WIESO ERZaeHLEN SIE MIR DAS, MEISTER ?", - "JA, MEISTER", - "MEISTER", - "WISSEN SIE, WIEVIEL UHR ES IST ?", - "Hae ?OH, DU HAST MICH GANZ SCHoeN ERSCHRECKT. BIST DU VON \"BLITZ UND BLANK BEI MONDESSCHEIN\"", - "ICH BIN IGOR, DER HAUSVERWALTER.DU KANNST MIT DEM WOHNZIMMER ANFANGEN. GESTERN HATTEN WIR EINE ueBERNATueRLICHE ORGIE UND ES SIEHT AUS WIE im SAUSTALL", - "KAUF ALLES WAS DU BRAUCHST !", - "DIE STEUERERKLaeRUNG.SIEHST DU DAS NICHT ?", - "ICH AUCH NICHT, WEIL DIE ZAHLEN SCHON MAL SEHR KLEIN SIND UND ICH DOCH kurzsichtig bin....", - "VON WEGEN ! SIE MACHEN MICH HaeSSLICH", - "PAH, DAS IST EINE RIESENFETE DIE DER MEISTER JEDESMAL DANN ABZIEHT, WENN IRGENDSOEIN IDIOT KOMMT, DER IHN ERLEDIGEN WILL", - " ZUERST REISSEN SIE IHM DIE AUGEN AUS DANACH GIESSEN SIE ZITRONENSAFT DRueBER DAMIT ES SCHoeN BRENNT UND DANN...", - "NEIN", - "WIE WARUM NICHT ? WEISST DU WIEVIEL UHR ES IST ?", - "im WINTER JA", - "TSCHueSS", - "WAG ES BLOOOSS NICHT !", - "GUT, FueR HEUTE REICHTS, DAS ABENDESSEN RUFT", - "IMMER VERGESSE ICH ZUZUSCHLIESSEN !", - "VERDAMMTER MIST NOCHMAL !", - "HaeH ?AH !SIE HABEN MICH GANZ SCHoeN ERSCHRECKT, MEISTER. ICH DACHTE SIE SCHLAFEN", - "ACH,ueBRIGENS, ICH HABE DIE WOHNZIMMERSCHLueSSEL GENOMMEN. SO NERVEN SIE MICH MORGEN FRueH NICHT MIT IHREN ZEICHENTRICKSERIEN", - "ACH, SIE HABEN SICH SCHON WIEDER ERKaeLTET, MEISTER ? ICH HAB JA IMMER SCHON GESAGT, SIE SOLLEN DIE HEIZUNG ANMACHEN...", - "NAJA, SCHLUCKEN SIE EINE SALICILACETYLSaeURE-TABLETTE UND AB INS BETT ZUM SCHWITZEN. GUTE NACHT", -}, -{ - "", - "MA\327TRE, JE CROIS QUE \200A NE ROULE PAS", - "J'EN SUIS TR\324S S\352R, MA\327TRE...", - "JE LE REGRETTE, MA\327TRE", - "IL APPORTERA UN AUTRE DE SCIENTIFIQUE FOU? JE VOUS PRVIENS QUE LE LABORATOIRE EN EST PLEIN ET TOUS SONT PRIMS", - "TAISEZ-VOUS, MA\327TRE, SI LES FMINISTES VOUS COUTENT...", - "CE QU'IL FAUT SUPPORTER!", - "MA\327TRE! -JE NE VOUS ATTENDAIT PAS SI T\342T!", - "A VA MAL MA\327TRE. IL DOIT AVOIR DES PROBL\324MES AVEC LE SATELLITE ET JE NE RUSSIT PAS \267 SINTONISER L'IMAGE. ET ENCORE L'ORAGE PRODUIT DES INTERFRENCES.", - "CANCANS QUE TOUT CELA, MA\327TRE!", - "OUI, MA\327TRE", - "MA\327TRE", - "QUELLE HEURE IL EST?", - "H\220? -AH! TU M'AS FAIT PEUR! TU EST CELUI DU \"NETTOYAGE DE NUIT\", NON?", - "JE SUIS IGOR, LE MAJORDOME. TU PEUX COMMENCER PAR LE SALON DE BAL. HIER IL Y A EU UNE ORGIE SURNATURELLE ET C'EST UNE SALOPERIE", - "SI TU AS BESOIN DE QUELQUE CHOSE, ACHETE-EN!", - "LA D\220CLARATION D'IMP\342TS, NE LE VOIS-TU PAS?", - "EH BIEN, MOI NON PLUS, CAR \267 CAUSE DE SI PETITS NUM\220ROS ET MA DIFFICULT\220 POUR BIEN VOIR DE LOIN...", - "ON N'EN PARLE PLUS! ILS ME FONT PARA\327TRE LAID", - "BAH! C'EST UNE BELLE F\322TE QUE LE MA\327TRE ORGANISE AVEC SES COLL\324GUES \267 CHAQUE FOIS QU'UN IMB\220CILE ARRIVE ET VEUT FINIR AVEC LUI", - "D'ABORD ON LUI ARRACHE LES YEUX; APR\324S, ON LUI VERSE DE JUS DE CITRON POUR QUE \200A LUI CUISE; APR\324S...", - "NON", - "POURQUOI PAS? TU AS VU L'HEURE QU'IL EST?", - "EN HIVER, OUI", - "AU REVOIR", - "N'Y PENSES M\322ME PAS!", - "BON, \200A VA POUR AUJOURD'HUI. JE VAIS D\327NER", - "J'OUBLIE TOUJOURS FERMER \267 CL\220, H\220LAS!", - "QUEL ENNUI!", - "H\220? -VOUS M'AVEZ FAIT PEUR, MA\327TRE. JE PENSAIS QUE VOUS DORMIEZ", - "H\220, MA\327TRE! PRENEZ LES CL\220S DE LA SALLE DE S\220JOUR, AINSI DONC SI VOUS VOULEZ VOIR LES DESSINS ANIM\220S DEMAIN DE BONNE HEURE NE ME D\220RANGEREZ PAS", - "QUOI? VOUS VOUS \322TES ENRHUM\220 ENCORE UNE FOIS, MA\327TRE? QUELLE CONTRARI\220T\220! JE VOUS AI D\220J\267 DIT D'Y METTRE LE CHAUFFAGE... ", - "BON, AVALEZ UN COMPRIM\220 D'ACIDEAC\220TYL SALICYLIQUE ET ALLEZ TRANSPIRER! BONNE NUIT!", -}, -{ - "", - "MAESTRO, CREDO CHE QUESTO NON VA", - "SICURISSIMO, MAESTRO", - "SCUSI, MAESTRO", - "VA A PORTARE UN ALTRO SCIENTIFICO PAZZO? GLI AVVERTO CHE IL LABORATORIO PIENO E NE ABBIAMO TUTTI SCADUTI", - "ZITTO, MAESTRO, FIGURASI SE LE SENTONO LE FEMMINISTE", - "ACCIDENTI!", - "-MAESTRO! NON LE ASPETTAVO COS\326 PRESTO!", - "MALE MAESTRO, DEVONO CI ESSERE PROBLEMI CON IL SATELLITE E NON RIESCO A SINTONIZZARE L'IMMAGINE. ANZI LA TEMPESTA CAUSA INTERFERENZE", - "CHE NE SO, MAESTRO", - "SI, MAESTROl", - "MAESTRO", - "SA CHE ORE SONO?", - "EH? -AH, CHE COLPO! TU SEI QUELLO DI \"PULIZIA NOTTURNA\" NO?", - "IO SONO IGOR, IL MAGGIORDOMO. PUOI COMINCIARE NEL SALOTTO DI BALLO, IERI C'ERA ORGIA SOPRANATURALE ED \220 PIENO DI MERDA", - "SE HAI BISOGNO DI QUALCOSA, COMPRALA", - "LA DECLARAZIONE DI REDDITI, NON VEDI?", - "NEANCH'IO, I NUMERI SONO PICCOLISSIMI E ANZI, IO NON VEDO BENE DA LONTANO", - "NEANCHE PARLARNE, MI FANNO SEMBRARE BRUTTO", - "\220 UNA FESTA CHE FA IL MAESTRO PER I SUOI AMICI OGNI VOLTA CHE ARRIVA QUALCHE IMBECILE CHE VUOLE FINIRE CON LUI", - "PRIMA, GLI TOGLIANO GLI OCCHI; POI GLI VERSANO SUCCO DI LIMONE, DOPO IL BRUCIORE.......", - "NO", - "COME CHE PER CHE NO? MA TU HAI VISTO CHE ORE SONO?", - "IN INVERNO, SI", - "ARRIVEDERCI", - "N\324 PENSARCI", - "BENE, BASTA PER OGGI. VADO A CENARE", - "E CHE SEMPRE DIMENTICO CHIUDERE CON LA CHIAVE", - "ACCIDENTI!", - "EH? -AH! CHE COLPO, MAESTRO, PENSAVO STAVA DURMENDO", - "ORA MI RICORDO, PRENDA LE CHIAVI DEL SOGGIORNO, COS\326 DOMANI MATTINA NON MI DISTURBA SE VUOLE GUARDARE I CARTONI ANIMATI", - "HA PRESSO FREDDO UN'ALTRA VOLTA, MAESTRO? SEMPRE GLI DICO CHE METTA IL RISCALDAMENTO", - "PRENDA UNA ASPIRINA ED A SUDARE. BUONA NOTTE", -}, -}; - - -const char *_textl[][32] = { -{ - "", - "ARE YOU GOING TO LET OURSELVES BE GUIDED BY PRIMITIVE INSTINCTS JUST BECAUSE WE BELONG TO DIFFERENT RACES AND THE SOCIAL SITUATION IS TELLING US TO DO SO?", - "AREN'T WE TIED BY SENSE WHICH IS THE MOST POWERFUL WEAPON AS WELL AS THE MOST PRECIOUS GIFT?", - "OH, IF WE ALL LET OUR THOUGHTS GUIDE OUR WAY IN LIFE WITHOUT LEAVING SOME ROOM FOR FEELINGS WHICH LET OUR PRE-EVOLUTIVE INSTINCTS COME OUT!", - "ANSWER ME, EPHEMERAL CREATURE. WOULDN'T WE ALL BE HAPPIER WITH THOSE EMOTIONAL BOUNDINGS?", - "YOU ARE NOT GETTING THROUGH", - "THIS IS A VERY CLEAR EXAMPLE, YOU SEE?: YOU WANT TO GET THROUGH AND GO AHEAD WITH YOUR ADVENTURE, AND I WON'T LET YOU DO THAT", - "WILL THAT BE A CONTROVERSIAL POINT BETWEEN US THAT HAVE JUST MET?", - "WELL THEN", - "WELL, THAT DEPENDS ON WHAT WE TAKE A RELATIONSHIP FOR. SOME AUTHORS DEFEND...", - "PUKE! HUNTING AS A WAY TO SURVIVE IS AN INCOMPATIBLE ARCHAIC THING FOR A SUPERIOR BEING LIKE ME. BESIDES, I'VE BECOME A VEGETARIAN", - "IT JUST HAPPENS THAT I WAS ACTUALLY EATING A GUY AND I STARTED TO BETHINK AND GET TO THE ABOVE MENTIONED THOUGHT", - "IT TOOK ME A LONG TIME TO QUIT OLD HABITS BUT AT LEAST MY IRASCIBLE SOUL BIT UP THE CONCUPISCIBLE ONE, AND EVER SINCE, I'VE NEVER EATEN MEAT AGAIN", - "NOT EVEN THE PLEASURE OF SUCKING UP THE BONE, FEELING THE TASTE OF THE SKIN AND THAT SWEET TASTE OF MARROW...THAT JUST TAKES YOU TO HEAVENLY PLACES", - "IT DOESN'T REALLY GET TO ME AT ALL", - "WHAT?", - "I DON'T KNOW WHAT YOU'RE TALKING ABOUT, YOU EPHEMERAL CREATURE", - "I'M NOT INTERESTED", - "I DON'T KNOW ABOUT THE OTHER GAMES, BUT WE COULD USE THIS BEAUTIFUL SCREEN", - "", - "I'D CARE...", - "NO. IT'S JUST THE SON, THE FATHER, THE GRANDFATHER AND A FRIEND, WHO ARE CALLED LIKE THAT", - "BUT, IT IS GOING TO LOOK LIKE THE GAME WAS MADE BY FIVE PEOPLE", - "THESE ARE PROMISING GUYS", - "THAT'S A GOOD ONE! A GOOD ONE!", - "PLEASE, CALL ME CONSTANTINO", - "IT WASN'T ME MAN. IT WAS \"EL COYOTE\", MY TWIN", - "JESUS, THESE ARE REALLY LONG CREDIT TITLES", - "I STOPPED COUNTING A LONG TIME AGO", - "WHAT WILL BECOME OF YOU NOW, DESIDERIO?", - "BUT, YOU SHOULD LOSE SOME WEIGHT", - "I'LL JUST RETIRE TO THE TIBET AND THINK ABOUT THE MEANING OF LIFE", -}, -{ - "", - "UN MOMENTO. \250SOLO PORQUE PERTENECEMOS A RAZAS DISTINTAS Y LA SOCIEDAD DICE QUE SEREMOS ENEMIGOS VAMOS A DEJARNOS LLEVAR POR NUESTROS MAS PRIMITIVOS INSTINTOS?", - "\250ACASO NO NOS UNE LA RAZON, ELARMA MAS PODEROSA Y, A LA VEZ, EL DON MAS PRECIADO QUE TENEMOS?", - "\255AH, SI EL ENTENDIMIENTO GUIARA NUESTROS PASOS POR LA VIDA SIN DEJAR SITIO A LOS SENTIMIENTOS, QUE AFLORAN NUESTRAS INCLINACIONES PRE-EVOLUTIVAS!", - "\250NO CREES QUE SERIAMOS MAS DICHOSOS SIN ESAS ATADURAS EMOCIONALES? CONTESTA EFIMERA CRIATURA", - "NO PASAS", - "\250VES? ESTE ES UN CLARO EJEMPLO: TU QUIERES PASAR Y CONTINUAR TU AVENTURA Y YO NO PUEDO PERMITIRLO", - "\250HA DE SER ESE MOTIVO SUFICIENTE DE CONFLICTO ENTRE NOSOTROS, QUE NO NOS CONOCEMOS DE NADA?", - "PUES ESO", - "BUENO, ESO DEPENDE DE LO QUE ENTENDAMOS POR RELACION. ALGUNOS AUTORES DEFIENDEN...", - "AGGG. LA CAZA COMO MEDIO DE SUBSISTENCIA ES UNA ACTIVIDAD ARCAICA INCOMPATIBLE CON UNA NATURALEZA SUPERIOR COMO LA MIA. Y ADEMAS ME HE VUELTO VEGETARIANO", - "RESULTA QUE ESTABA COMIENDOME A UN TIO Y ME PUSE A REFLEXIONAR. LLEGUE A LA CONCLUSION ANTES MECIONADA", - "ME COSTO MUCHO DEJAR LOS HABITOS DESDE TANTO TIEMPO ADQUIRIDOS, PERO POR FIN MI ALMA IRASCIBLE VENCIO A LA CONCUPISCIBLE Y NO HE VUELTO A PROBAR LA CARNE", - "NI SIQUIERA EL PLACER QUE SUPONE UN HUESO, CON EL JUGO DE LA PIEL ENTRE SUS POROS Y ESE SABOR QUE TE TRANSPORTA A LUGARES REMOTOS PARADISIACOS...", - "NI SIQUIERA ME AFECTA. PARA NADA, DE VERDAD", - "\250EL QUE?", - "NO SE DE QUE ME HABLAS, EFIMERA CRIATURA", - "NO ME INTERESA", - "LOS DEMAS JUEGOS, NO SE, PERO ESTE PARA APROVECHAR ESTA PANTALLA TAN BONITA", - "", - "A MI SI ME DARIA", - "NO, ES QUE SON EL ABUELO, EL PADRE, EL HIJO, Y UN AMIGO QUE SE LLAMA ASI", - "NO, PERO ES QUE SI NO VA A PARECER QUE HAN HECHO EL JUEGO ENTRE CINCO", - "ESTOS CHICOS PROMETEN", - "\255ESE ES BUENO, ESE ES BUENO!", - "LLAMAME CONSTANTINO", - "NO ERA YO, HOMBRE. ERA MI DOBLE, EL COYOTE", - "VAYA, QUE CREDITOS MAS LARGOS", - "YO YA PERDI LA CUENTA", - "BUENO DESIDERIO, \250Y QUE VA A SER DE TI AHORA?", - "PERO TENDRIAS QUE ADELGAZAR", - "ME RETIRARE AL TIBEL A REFLEXIONAR SOBRE EL SENTIDO DE LA VIDA", -}, -{ - "", - "MOMENT mal. NUR WEIL WIR UNTERSCHIEDLICHER HERKUNFT SIND UNd eigentlich feinde sein muessten mueSSEN WIR UNS DOCH Nicht wie die primaten auffuehren!", - "VERBINDET UNS ETWA NICHT DIE VERNUNFT, GEFaeHRLICHSTE WAFFE UND ZUGLEICH GRoeSSTE GABE, DIE WIR HABEN ?", - "AH, WENN NUR DAS GEGENSEITIGE VERSTaeNDNIS die gefuehle besiegen koennte,DIE DIE WURZEL UNSERER PRaeHISTORISCHEN NEIGUNGEN SIND!", - "GLAUBST DU NICHT, DASS WIR OHNE DIESE GEFueHLSFESSELN GLueCKLICHER WaeREN ? ANTWORTE, DU EINTAGSFLIEGE", - "DU KOMMST NICHT DURCH", - "SIEHST DU ? DU WILLST HIER DURCH UND MIT DEM ABENTEUER WEITERMACHEN UND ICH KANN DAS NICHT ZULASSEN", - "MUSS DENN DIE TATSACHE, DASS WIR UNS NICHT KENNEN, ANLASS ZUM STREIT SEIN?", - "GENAU", - "NAJA. KOMMT DARAUF AN, WAS WIR UNTER BEZIEHUNG VERSTEHEN. EINIGE VERTRETEN JA DEN STANDPUNKT, DASS....", - "ARRGH.nur zu jagen, um zu ueberleben ist mir zu primitiv.UND AUSSERDEM BIN ICH SEIT KURZEM VEGETARIER", - "ES GING LOS,ALS ICH MIR GERADE EINEN TYPEN EINVERLEIBTE UND ANFING NACHZUDENKEN UND ZUM EBENERWaeHNTEN SCHLUSS KAM", - "ES war hart, DIE ALTEN laster ABZULEGEN, ABER seit MEINE FLEISCHESLUST MEINEn JaeHZORN besiegt hat HABE ICH KEIN FLEISCH MEHR GEGESSEN:", - "NICHT MAL DIE GAUMENFREUDE EINES KNOCHENS, MIT DEM SAFT DER HAUT IN DEN POREN UND DIESEm GESCHMACK DER DICH INS REICH DER SINNE ENTFueHRT...", - "ES MACHT MIR ueBERHAUPT NICHTS AUS, WIRKLICH", - "WAS JETZT ?", - "ICH WEISS NICHT, WOVON DU REDEST, DU EINTAGSFLIEGE", - "DAS INTERESSIERT MICH NICHT", - "ANDERE SPIELE, ACH ICH WEISS NICHT, ABER DAS HIER HAT SO EINE NETTE GRAFIK", - "ICH HaeTTE SCHON LUST..", - "NEIN, SO HEISSEN DER OPA, DER VATER, DER SOHN UND EIN FREUND.", - "NEIN, ABER WENN NICHT, SIEHT ES SO AUS ALS WaeRE DAS SPIEL VON FueNF LEUTEN GEMACHT WORDEN", - "DIESE JUNGS SIND VIELVERSPRECHEND !", - "DER IST GUT, SUPERKLASSE !", - "NENN MICH KONSTANTIN", - "MANN, DAS WAR NICHT ICH, SONDERN MEIN DOUBLE, DER KOYOTE", - "WOW, WAS FueR EINE LANGE DANKESLISTE", - "ICH HAB SCHON DEN ueBERBLICK VERLOREN", - "O.K. DESIDERIO, UND WAS WIRD JETZT AUS DIR WERDEN ?", - "ABER DANN MueSSTEST DU ABNEHMEN", - "ICH WERDE NACH TIBET AUSWANDERN UND ueBER DEN SINN DES LEBENS NACHDENKEN", -}, -{ - "", - "c'est parce qu'on APPARTIENT \267 DES RACES DIFF\220RENTES ET QUE LA SOCI\220T\220 NOUS CONFRONTE, QUE NOUS ALLONS AGIR PAR NOS PLUS M\220PRISABLES INSTINCTS?", - "NE SOMMES-NOUS PAR HASARD ACCROCHS PAR LA RAISON, L'ARME LA PLUS PUISSANTE, ET AUSSI LE DON LE PLUS PRCIEUX QUE NOUS AVONS?", - "AH!, SI LA RAISON GUIDAIT NOS PAS DANS LA VIE SANS Y ENTRA\327NER LES SENTIMENTS, QUI FONT JAILLIR NOS INCLINAISONS PR-VOLUTIVES!", - "NE CROIS-TU PAS QUE NOUS SERIONS PLUS HEREUX SANS CES ATTACHEMENTS-L\267? RPONDS-MOI, CRATURE PHM\324RE ", - "TU NE PASSES PAS", - "TU VOIS? C'EST UN EXEMPLE CLAIR: TOI, TU VEUX PASSER ET POURSUIVRE TON AVENTURE ET MOI, JE NE PEUX PAS LE TOLRER", - "CELA DOIT \322TRE UNE RAISON SUFFISANTE DE CONFLIT ENTRE NOUS DEUX, QUI NE NOUS CONNAISSONS DE RIEN?", - "C'EST CELA", - "EH BIEN, CELA DPEND DE CE QU'ON ENTEND PAR RLATION. D'APR\324S QUELQUES AUTEURS...", - "LA CHASSE COMME MOYEN DE SUBSISTANCE EST UNE ACTIVIT\220 ARCHA\330QUE, INCOMPATIBLE AVEC ma NATURE SUP\220RIEURE . ET DE PLUS JE SUIS DEVENU V\220G\220TARIEN", - "IL S'EN SUIT QU'EN TRAIN DE D\220VORER UN TYPE, JE ME SUIS MIS \267 R\220FL\220CHIR. ALORS, SUIS ARRIV\220 \267 LA CONCLUSION MENTIONN\220 CI-DESSUS", - "ABANDONNER CES HABITUDES M'EST REVENU CHER, MAIS \267 LA FIN MON \266ME IRASCIBLE a vancue MON \266ME CONCUPISCIBLE, ET D\324S LORS JE N'AI GO\352T\220 \267 LA VIANDE", - "M\322ME PAS LE PLAISIR DE CROQUER UN OS, AVEC LE SUC DE LA PEAU ENTRE SES PORES ET sa SAVEUR QUI TE TRANSPORTE VERS DES LIEUX TR\324S LONTAINS, PARADISIAQUES...", - "CECI NE M'AFFECTE PAS M\322ME, ABSOLUMENT PAS, C'EST VRAI", - "QUOI?", - "JE NE SAIS PAS DE QUOI TU M'EN PARLES, CR\220ATURE \220PH\220M\324RE", - "CELA NE ME REGARDE PAS", - "LES AUTRES JEUX, JE NE SAIS PAS; MAIS CELUI-CI OUI, POUR EN PROFITER DE CET \220CRAN SI JOLI", - "", - "MOI, JE NE M'EN FICHERAI PAS", - "NON, C'EST QU'ILS SONT LE GRAND-P\324RE, LE P\324RE, LE FILS, ET UN AMI QUI S'APPELLE COMME \200A", - "NON, MAIS SI NON, IL VA PARA\327TRE QU'ON A FAIT LE JEU ENTRE CINQ", - "CES GAR\200ONS ONT DU FUTUR", - "CELUI-L\267 EST BON! CELUI-L\267 EST BON!", - "APPELLE-MOI CONSTANTIN", - "CE N'\220TAIT PAS MOI, MON VIEUX. C'\220TAIT MON DOUBLE, LE COYOTE", - "TIENS! QUELS CR\220DITS SI LONGS", - "J'AI D\220J\267 PERDU LES COMPTES", - "EH BIEN, D\220SID\324RE, QUE T'ARRIVERA-T-IL MAINTENANT?", - "MAIS TU DEVRAIS MAIGRIR", - "JE VAIS ME RETIRER AU TIBEL POUR Y R\220FL\220CHIR SUR LE SENS DE LA VIE", -}, -{ - "", - "UN ATTIMO. PERCHE SIAMO DI DIVERSE RAZZE E LA SOCIET\265 DICA CHE SIAMO NEMICI, ANDIAMO A LASCIARCI DOMINARE PER I PI\351 PRIMITIVI ISTINTI?", - "MA NON SIAMO UNITI DALLA RAGIONE, DALLA ARMA PI\351 PODEROSA E ANCHE PER IL DONO PI\351 PREZIOSO CHE ABBIAMO?", - "SE IL GIUDIZIO GUIDASSE I NOSTRI PASSI NELLA VITA SENZA LASCIARE POSTO AI SENTIMENTI, CHE MOSTRANO LE NOSTRE INCLINAZIONI PRE-EVOLUTIVI!", - "NON CREDI CHE SAREMMO PI\351 BEATI SENZA QUESTO LEGAME EMOZIONALE? RISPONDE EFFIMERA CREATURA", - "NON PASSI", - "VEDI? QUESTO UN CHIARO ESEMPIO: TU VUOI PASSARE E PROSEGUIRE LA TUA AVVENTURA ED IO NON POSSO PERMETTERLO", - "MA DEVE ESSERE CAUSA DI CONFRONTO QUANDO ANCORA NON CI CONOSCIAMO?", - "CHE TI HO DETTO?", - "BOH, DIPENDE DI CHE CAPIAMO COME RELAZIONE. CI SONO AUTORI CHE DIFENDONO...", - "LA CACCIA COME FORMA DI SUSSISTENZA \220 UNA ATTIVIT\265 ARCAICA, INCOMPATIBILE CON UNA NATURA SUPERIORE COM'\220 LA MIA: ADESSO SONO VEGETARIANO", - "TEMPO FA, STAVO MANGIANDO UN TIZIO QUANDO MI SONO MESSO A RIFLETTERE. FU QUANDO LA CONCLUSIONE DI PRIMA ARRIV\220 ", - "FU DIFFICILE LASCIARE LE MIE VECCHIE ABITUDINI, MA LA MIA ANIMA IRASCIBILE HA VINTO LA CONCUPISCIBILE E NON MANGIO PI\351 DELLA CARNE", - "NEPPURE IL PIACERE CHE FA UN OSSO, COL SUCCO DELLA PELLE E QUEL SAPORE CHE TI PORTA A POSTI LONTANI E PARADISIACI...", - "NEMMENO MI TOCCA DA VICINO, DAVVERO", - "CHE COSA?", - "NON SO SU CHE MI PARLI, EFFIMERA CREATURA", - "NON MI INTERESA", - "GLI ALTRI VIDEO-GIOCHI, NON SO, MA QUESTO \220 PER APPROFITTARE QUESTO BELLO SCHERMO", - "", - "IO SI ME VERGOGNAREI", - "NO, SONO IL NONNO, IL PADRE, IL FIGLIO, E UN AMICO CHE SI CHIAMA COS\326 ", - "NO, MA SE NON \220 COS\326, SEMBRAR\265 CHE HANNO FATTO IL VIDEO-GIOCO IN CINQUE", - "BRAVI RAGAZZI", - "-QUELLO \220 BUONO, QUELLO \220 BUONO!", - "CHIAMAMI COSTANTINO", - "NON ERO IO, DAI,. ERA IL MIO CONTROFIGURA, IL COYOTE", - "INSOMMA, MOLTI TITOLI DI CODA", - "IO NON SO GI\265 QUANTI", - "ALLORA PEPPINO, CHE VAI FARE ADESSO?", - "MA DOVRESTI DIMAGRIRE", - "MI APPARTER\220 AL TIBET A RIFLETTERE SUL SENSO DELLA VITA", -}, -}; - -const char *_textp[][20] = { -{ - "", - "HI", - "YES SIR. IT'S BEAUTIFUL", - "NO, NO. HE WON'T DO IT", - "ALL RIGHT THEN", - "REALLY?", - "SO?", - "I'M SORRY. THE PIANIST UNION TRADE DOESN'T ALLOW ME TO SAVE GIRLS FROM VAMPIRES' CLUTCHES", - "IF SHE HAD BEEN KIDNAPPED BY THE WEREWOLF...", - "I CAN ONLY PLAY THIS SONG", - "I'M A CONSERVATOIRE PIANIST AND THE BARTENDER WON'T BUY MORE SCORES FOR ME", - "OH GOD, I REALLY LOVE CLASSIC MUSIC!", - "IT'S BECAUSE I'M WEARING EAR-PLUGS", - "IT'S BECAUSE I CAN LIP-READ", - "NOOO", - "NO! I'M NOT TAKING THIS ANY LONGER!", - "NO WAYYYYY!", - "WHAT? OF COURSE I'M INTERESTED", - "THANKS GOD! I CAN PLAY A DIFFERENT SONG NOW!", - "I GUESS YOU CAN KEEP MY EAR-PLUGS", -}, -{ - "", - "HOLA", - "BONITA. SI SE\245OR", - "NO QUE NO LO HACE", - "PUES VALE", - "\250SI?", - "\250Y?", - "LO SIENTO. EL SINDICATO DE PIANISTAS NO ME PERMITE RESCATAR CHICAS DE LAS GARRAS DE LOS VAMPIROS", - "SI LA HUBIERA RAPTADO UN HOMBRE LOBO...", - "NO PUEDO TOCAR MAS QUE ESTA CANCION", - "ES QUE SOY PIANISTA DE CONSERVATORIO Y EL TABERNERO NO COMPRA MAS PARTITURAS", - "\255CON LO QUE A MI ME GUSTA LA MUSICA CLASICA!", - "PORQUE LLEVO TAPONES EN LOS OIDOS", - "PORQUE LEO LOS LABIOS", - "NOOO", - "\255QUE NO! \255QUE NO ME AGUANTO!", - "\255QUE NOOOOOO!", - "\250QUE? CLARO QUE ME INTERESA", - "AHORA PODRE TOCAR OTRA CANCION \255QUE ALIVIO!", - "SUPONGO QUE TE PUEDES QUEDAR CON MIS TAPONES", -}, -{ - "", - "HALLO", - "JAWOLL, SEHR SCHoeN", - "NEIN, ER TUT ES EINFACH NICHT", - "NA GUT, OK.", - "JA ?", - "UND ?", - "TUT MIR LEID. DIE KLAVIERSPIELERGEWERKSCHAFT ERLAUBT ES MIR NICHT, MaeDCHEN AUS DEN KLAUEN VON VAMPIREN ZU BEFREIEN", - "WENN SIE WERWOLF ENTFueHRT HaeTTE.....", - "ICH KANN NUR DIESES EINE LIED", - "ICH HABE AM KONSERVATORIUM KLAVIER GESPIELT UND DER WIRT WILL MEINE PARTITueDEN NICHT KAUFEN", - "WO MIR DOCH KLASSISCHE MUSIK SO GUT GEFaeLLT !", - "WEIL ICH OHRENSToePSEL IN DEN OHREN HABE", - "WEIL ICH VON DEN LIPPEN LESEN KANN", - "NEEEIN", - "NEEIEN! ICH KANN MICH NICHT BEHERRSCHEN !", - "NEIN,NEIN,UND NOCHMAL NEIN !", - "WIE BITTE ? KLAR BIN ICH INTERESSIERT", - "ENDLICH KANN ICH WAS ANDERES SPIELEN,WELCH ERLEICHTERUNG !", - "ICH GLAUBE, DU KANNST MEINE OHRENSToePSEL BEHALTEN", -}, -{ - "", - "BONJOUR!", - "JOLIE, OUI M'SIEUR", - "NON, QU'ELLE NE LE FAIT PAS", - "D'ACCORD, A VA", - "OUI?", - "ET QUOI?", - "SUIS DSOL. LE SYNDICAT DE PIANISTES NE ME PERMET PAS DE LIBRER LES FILLES DES GRIFFES DE VAMPIRES", - "SI ELLE AVAIT T RAPTE PAR UN HOMME-LOUP...", - "JE NE PEUX PAS JOUER DAVANTAGE CETTE CHANSON", - "JE SUIS LE PIANISTE DU CONSERVATOIRE ET LE TAVERNIER N'ACH\324TE PAS MES PARTITIONS", - "ET MOI QUI AIME BEAUCOUP LA MUSIQUE CLASSIQUE!", - "PARCE QUE J'AI DES TAMPONS \267 L'OU\330E", - "PARCE QUE JE LIS LES LEVRES", - "NOOON!", - "QUE NON! QUE JE NE PEUX PAS ME RETENIR DAVANTAGE!", - "QUE NOOOOOON!", - "QUOI? BIEN S\352R QUE \200A M'INT\220RESSE", - "MAINTENANT JE POURRAI JOUER UNE AUTRE CHANSON -QUEL SOULAGEMENT!", - "TU PEUX GARDER MES TAMPONS, JE SUPPOSE", -}, -{ - "", - "CIAO", - "BELLA, MOLTO BELLA", - "NO, CHE NON LO FA", - "VA BENE", - "-SI?", - "E?", - "MI DISPIACE. IL SINDACATODI PIANISTI NON MI DA PERMESSO PER LIBERARE RAGAZZE DALLE MANI DI VAMPIRI", - "SE LA AVESSE SEQUESTRATA IL LUPO-MANNARO...", - "SOLTANTO POSSO SUONARE QUESTA CANZONE", - "\324 PERCHE SONO PIANISTA DI CONSERVATORIO E IL TABERNERO NON COMPRA PI\353 PARTITURE", - "PECCATO.....MI PIACE MOLTISSIMO LA MUSICA CLASSICA!", - "PERCHE MI HO MESSO TAPPI NEGLI ORECCHII", - "PERCHE SO LEGGERE LE LABRA", - "NOOO", - "NO!, NON MI SOPPOROTO!", - "HO DETTO DI NOOO!", - "COSA? SI, SI MI INTERESA, COME NO", - "ADESSSO POTR\343 SUONARE UN'ALTRA CANZONE, GRAZIE!!", - "CREDO CHE I MIEI TAPPI ADESSO SONO TUOI", -}, -}; - - -const char *_textt[][25] = { -{ - "", - "WHAT HAPPENS, WHAT'S THE MATTER?", - "OK. ROOM 512. UPSTAIRS. THE KEY IS ON THE DOOR", - "COUNT DRASCULA!!?", - "NO, NOTHING. THAT GUY HAS A BAD REPUTATION OVER HERE", - "WELL, THERE ARE ALL KINDS OF STORIES GOING AROUND ABOUT HIM, SOME SAY HE IS A VAMPIRE WHO KIDNAPS PEOPLE TO SUCK UP THEIR BLOOD", - "HOWEVER, SOME OTHERS SAY THAT HE IS JUST AN ORGAN-DEALER AND THAT IS THE REASON WHY THERE ARE BODY PARTS ALL OVER THE PLACE", - "BUT OF COURSE, THOSE ARE JUST RUMORS. HE'S PROBABLY BOTH THINGS. BY THE WAY, WHY DO YOU WANT TO MEET HIM?", - "NO, FORGET IT. I'M REALLY BUSY...", - "WELL, OK. BUT JUST BECAUSE I WANT TO DO IT, NOT BECAUSE YOU TELL ME TO", - "THEY'RE WINNING", - "LEAVE ME ALONE, ALL RIGHT?", - "OF COURSE. I'M NOT BLIND", - "THE TRADITION IN THIS VILLAGE IS TO FORGET ALL HARD FEELINGS WHENEVER THERE IS A GAME, SO AS TO CHEER UP THE LOCAL TEAM", - "AND PLEASE, SHUT UP FOR GOD'S SAKE. I CAN'T HEAR ANYTHING!", - "COME ON, LEAVE ME ALONE AND DON'T BOTHER ME ANYMORE", - "IT HAS JUST STARTED! AND SHUT UP!", - "OK, OK, I THOUGHT SOMETHING WAS GOING ON", - "IT DOESN'T MATTER, ANYWAY. SHE'LL PROBABLY BE DEAD BY NOW", - "HE JUST STARTED PLAYING CLASSIC MUSIC, AND I COULDN'T STAND IT", - "SINCE I'M PAYING HIM FOR PLAYING WHATEVER I WISH, I JUST FIRED HIM", - "AND THEN, HE GOT FRESH WITH ME. JESUS!, HE LOOKED SO NICE AND INNOCENT...WHAT A HYPOCRITE!", - "BY THE WAY, BE CAREFUL BECAUSE I JUST WAXED THE FLOOR", - "SHUT UP! WE'RE WATCHING THE GAME!", - "OH, COME ON! TAKE IT!", -}, -{ - "", - "\250QUE PASA, QUE PASA?", - "DE ACUERDO. HABITACION 512. SUBIENDO POR LAS ESCALERAS. LA LLAVE ESTA EN LA PUERTA", - "\255\250 EL CONDE DRASCULA ?!", - "NO, NADA. ESE TIPO TIENE MALA FAMA POR AQUI", - "BUENO, CORREN VARIOS RUMORES SOBRE EL. ALGUNOS DICEN QUE ES UN VAMPIRO Y VA SECUESTRANDO GENTE PARA CHUPARLES LA SANGRE", - "CLARO, QUE OTROS OPINAN QUE SOLO ES UN TRAFICANTE DE ORGANOS, Y POR ESO APARECE GENTE DESCUARTIZADA POR LOS ALREDEDORES", - "POR SUPUESTO SON SOLO RUMORES. LO MAS PROBABLE ES QUE SEA LAS DOS COSAS. POR CIERTO, \250PARA QUE QUIERE USTED VER A ESE TIPO?", - "NO DEJELO, QUE ES QUE TENGO MUCHO QUE HACER...", - "BUENO VALE, PERO PORQUE QUIERO YO, NO PORQUE LO DIGAS TU", - "VAN GANANDO", - "DEJAME EN PAZ, \250VALE?", - "PUES CLARO, NO SOY CIEGO", - "ES TRADICION EN EL PUEBLO QUE CUANDO HAY PARTIDO SE OLVIDAN RENCORES PARA ANIMAR A LA SELECCION", - "Y CALLATE YA DE UNA VEZ, QUE NO ME DEJAS OIR", - "ANDA, DEJAME EN PAZ Y NO MOLESTES", - "\255ACABA DE EMPEZAR! \255Y CALLATE!", - "AH, BUENO. CREIA QUE PASABA ALGO", - "NO, SI ES IGUAL. A ESTAS HORAS YA ESTARA MUERTA", - "ES QUE SE PUSO A TOCAR MUSICA CLASICA Y YO NO LA AGUANTO", - "Y COMO YO LE PAGO PARA QUE TOQUE LO QUE YO QUIERO, PUES LE HE ECHADO", - "Y ENCIMA SE ME PUSO CHULO... \255Y PARECIA UNA MOSQUITA MUERTA!", - "...POR CIERTO, TENGA CUIDADO. EL SUELO ESTA RECIEN ENCERADO", - "\255SILENCIO! \255ESTAMOS VIENDO EL PARTIDO!", - "\255VENGA, ANDA! TOMA.", -}, -{ - "", - "WAS ZUM TEUFEL IST LOS ?", - "O.K. ZIMMER 512. DIE TREPPE HOCH. DIE SCHLueSSEL STECKEN SCHON", - " GRAF DRASCULA ? !", - "NEIN, DER TYP HAT HIER EINEN SCHLECHTEN RUF", - "NAJA, ES GIBT MEHRERE GERueCHTE ueBER IHN. EINIGE BEHAUPTEN, DASS ER LEUTE ENTFueHRT UND IHNEN DAS BLUT AUSSAUGT", - "KLAR, ANDERE GLAUBEN, DASS ER EIN ORGANHaeNDLER IST UND DESHALB TAUCHEN ueBERALL AM WALDRAND ZERSTueCKELTE LEICHEN AUF", - "NATueRLICH SIND DAS ALLES NUR GERueCHTE. HoeCHSTWAHRSCHEINLICH STIMMEN SIE ABER. ACH, UND WAS WOLLEN SIE VON IHM ?", - "NEIN, VERGESSEN SIES. ICH HABE NaeMLICH ZU TUN...", - "O.K. ABER WEIL ICH DAS WILL UND NICHT WEIL DU DAS SAGST", - "SIE GEWINNEN", - "LASS MICH IN RUHE, OK ?", - "KLAR, ICH BIN DOCH NICHT BLIND", - "ES IST EIN ALTER BRAUCH IM DORF, DASS MAN BEI EINEM SPIEL ALTE ZWISTE VERGISST, UM DIE MANNSCHAFT ANZUFEUERN", - "UND HALT ENDLICH DEINEN MUND, ICH WILL ZUHoeREN", - "MANN, LASS MICH IN RUHE UND NERV MICH NICHT", - "ES FaeNGT GERADE AN ! STILL JETZT !", - "ACH SO, ICH DACHTE ES IST IRGENDWAS LOS", - "NEIN, IST DOCH EGAL. JETZT WIRD SIE EH SCHON TOT SEIN", - "ER HAT KLASSIK GESPIELT UND ICH HALTE DAS NICHT AUS", - "UND WEIL ICH ES BIN, DER IHN DAFueR BEZAHLT, DASS ER SPIELT, WAS ICH WILL, HABE ICH IHN ENTLASSEN", - "UND DANN KAM ER MIR AUCH NOCH SCHRaeG... UND WAS FueR EINE PAPPNASE ER DOCH IST !", - "...ACH JA, UND PASSEN SIE AUF. DER BODEN IST FRISCH GEBOHNERT", - "RUHE !WIR GUCKEN GERADE DAS SPIEL !", - "LOS, HAU REIN, GIBS IHM", -}, -{ - "", - "QU'EST-CE QU'IL Y A, QU'Y A-T-IL?", - "D'ACCORD. CHAMBRE 512. PAR LES ESCALIERS. LA CL EST SUR LA PORTE", - "LE COMTE DRASCULA?!", - "NON, RIEN, CE TYPE A UNE MAUVAISE RPUTATION PAR ICI", - "EH BIEN, IL Y A DES RUMEURS QUI COURENT SUR LUI. CERTAINS DISENT QUE C'EST UN VAMPIRE ET QU'IL ENLEVE DU MONDE POUR SUCER LEUR SANG ", - "MAIS D'AUTRES PENSENT QU'IL EST SEULEMENT UN TRAFICANT D'ORGANES, ET C'EST POUR CELA QUE DES PERSONNES DPECES SONT APPARUES DANS LES ALENTOURS", - "CERTAINEMENT IL NE S'AGIT QUE DES BRUITS QUI COURENT. S\352REMENT IL AURA LES DEUX MTIERS. MAIS, POURQUOI VOULEZ-VOUS VOIR CE TYPE?", - "OH, NON! OUBLIEZ CELA, J'AI BEAUCOUP \267 FAIRE.", - "BON, A VA. MAIS PARCE QUE JE VEUX ET NON PARCE QUE TU LE DIS", - "ILS GAGNENT", - "FICHE-MOI LA PAIX, D'ACCORD?", - "C'EST S\352R, JE NE SUIS PAS UN AVUGLE", - "SELON LA TRADITION DU VILLAGE, QUAND IL Y A UN MATCH ON OUBLIE LES RANCUNES, POUR ALLER ENCOURAGER LA S\220LECTION", - "ET FERME-LA D'UNE FOIS!, JE NE PEUX PAS ENTENDRE", - "ALLEZ, VA-T'-EN ET NE D\220RANGES PAS!", - "\200A VIENT DE COMMENCER! -ET TAIS-TOI!", - "AH, BON! JE PENSAIS QU'IL SE PASSAIT QUELQUE CHOSE", - "NON, C'EST \220GAL. \267 CES HEURES-CI ELLE SERA D\220J\267 MORTE", - "LE FAIT EST QU'ELLE A COMMENC\220 JOUER DE LA MUSIQUE CLASSIQUE ET QUE JE NE SUPPORTE PAS CELA", - "ET MAINTENANT QUE JE LUI AI MIS DEHORS, COMMENT JE LUI PAIE POUR QU'IL JOUE CE QUE JE VEUX", - "ET ENCORE IL S'EST MONTR\220 ARROGANT... -ET DIRE QU'IL PARAISSAIT UNE SAINTE-NITOUCHE!", - "...FAITES ATTENTION, ON VIENT DE CIRER LE PARQUET", - "SILENCE! ON VOIT LE MATCH!", - "OH L\267 L\267! TIENS!", -}, -{ - "", - "CHE SUCCEDE, CHE SUCCEDE?", - "D'ACCORDO. CAMERA 512. DEVE SALIRE LE SCALE. LA CHIAVE \324 NELLA PORTA", - "IL CONDE DRASCULA?", - "NO, NIENTE. QUEL TIZIO HA MALA REPUTAZIONE QU\336", - "SE DICONO MOLTE COSE SU LUI. COME CH'\324 UN VAMPIRO E SEQUESTRA GENTE PER BERE LA SUA SANGUE", - "ALTRI DICONO CHE SOLO \324 UN TRAFFICANTE DI ORGANI, PER QUELLO TROVIAMO GENTE SQUARTATA FUORI LE MURA", - "SONO SOLTANTO CHIACCHIERE. FORSE SIA LE DUE COSE. MA, PERCHE VUOLE TROVARE QUEL TIZIO?", - "NO, HO MOLTO DA FARE..", - "VA BENE, MA PERCHE VOGLIO IO, NON PERCHE L'ABBIA DETTO TU", - "ADESSO VINCONO", - "LASCIAMI IN PACE, O.K.?", - "CERTO, NON SONO CIECO", - "C'\324 LA TRADIZIONE NEL PAESE DI DIMENTICARE I RANCORI QUANDO C'\324 PARTITA DI CALCIO; PER ANIMARE LA SELEZIONE", - "TI HO DETTO DI STARE ZITTO, NON RIESCO A SENTIRE", - "LASCIAMI IN PACE E NON MI DISTURBARE", - "\324 APPENA COMINCIATO, ZITTO!", - "AH, BENE. HO PENSATO CHE SUCCEDEVA QUALCOSA", - "NO, NON FA NIENTE. ADESSO SICURO CH'\324 GI\267 MORTA", - "SI \324 MESSO A SUONARE MUSICA CLASSICA ED IO LA ODIO", - "\324 COME FACCIO PER SENTIRE QUELLO CHE VOGLIO SE L'HO LICENZIATO", - "E ORA SI METTE BULLO...-E SEMBRAVA PROPRIO SCEMO!", - "...SENTA! FACCIA ATTENZIONE. IL PAVIMENTO \324 APPENA INCERATO", - "ZITTO! - STIAMO GUARDANDO LA PARTITA!", - "DAI! PRENDI", -}, -}; - - -const char *_textvb[][63] = { -{ - "", - "WHO THE HELL IS CALLING AT THIS TIME?", - "OH, ..OH, NO, NO....I'M...GANIMEDES THE DWARF. PROFESSOR VON BRAUN DOESN'T LIVE HERE ANYMORE", - "NO, I DON'T KNOW WHERE IT IS !!", - "GET OUT!!", - "IT'S TOO LATE NOW, YOU IDIOT!! IT ALWAYS IS", - "I COULDN'T AGREE MORE", - "ME, SCARED?", - "LISTEN HERE, DUDE. YOU'RE RIGHT NOW TALKING TO THE ONLY PERSON WHO KNOWS THE SECRET TO FIGHT AGAINST THE VAMPIRE", - "YOU NEED TO HAVE SPECIAL SKILLS TO FIGHT AGAINST A VAMPIRE. NOT EVERYBODY CAN DO IT", - "YOU DON'T HAVE THEM", - "I'M SURE YOU WOULDN'T BET ALL YOUR MONEY ON IT, HUH?", - "WELL, ALL RIGHT, COME ON IN", - "IF YOU REALLY MEAN TO FACE DRASCULA, YOU'VE GOT TO BE ABLE TO TAKE ALL TYPES OF CREAKING AND VAMPIRE-LIKE NOISES", - "IS THAT CLEAR?", - "OK, WAIT A MINUTE", - "STAND IN THE CENTER OF THE ROOM, PLEASE", - "WHERE DID I PUT THAT RECORD CALLED \"NAILS SCRATCHING THE BLACKBOARD\"?", - "ALL RIGHT. LET'S GET TO IT", - "YOU ARE USELESS. YOU SEE...?, JUST LIKE THE REST!!", - "JUST GIVE ME NOW THE MONEY YOU LOST AND GET OUT OF HERE", - "AND DON'T COME BACK UNTIL YOU ARE ABSOLUTELY READY", - "WHAT DO YOU WANT NOW?", - "I HAVE TO ADMIT IT. YOU REALLY GOT WHAT IT TAKES TO FIGHT AGAINST THE VAMPIRES", - "HEY, TAKE YOUR MONEY. I ADMIT IT WHEN I MAKE A MISTAKE...", - "LEAVE ME ALONE NOW, I WANT TO GET SOME SLEEP", - "WHENEVER YOU ARE READY TO FIGHT AGAINST THE VAMPIRES, JUST COME BACK AND I'LL HELP YOU OUT", - "OH, THAT'S EASY. JUST USING THE LIGHT OF ONE CRUCIFIX IS ENOUGH TO DESTROY HIM", - "YOU HAVE TO BE EXTRA CAREFUL WITH DRASCULA, HIS FRISISNOTICS POWERS HAVE MADE OF HIM THE MOST POWERFUL VAMPIRE", - "YOU'D BE LOST IF IT WASN'T FOR THEY...", - "...BREW!", - "YEAH, YOU'RE RIGHT! I MIGHT HAVE SOME PROBLEMS WITH MY BACK IN THE FUTURE IF I KEEP ON SLEEPING THIS WAY", - "I UNDERSTAND HE WAS A BETTER OPPONENT THAN ME, BUT YOU HAVE TO ADMIT THAT THE DISCOVERY I MADE ABOUT ANTI-VAMPIRE TECHNIQUES WAS WHAT ACTUALLY PROTECTED ME", - "I'VE FOUND THIS IMMUNIZING BREW THAT KEEPS YOU SAFE FROM ANY VAMPIRES' BITE OR AGAINST HIS FRISISNOTICS POWERS", - "NO, NO, EXCUSE ME. I HAD IT ONCE BUT IT'S VERY DANGEROUS TO HAVE A BREW OF THAT TYPE. CAN YOU IMAGINE WHAT COULD HAPPEN IF A VAMPIRE GOT IT?", - "HE'D BE IMMUNIZED AGAINST GARLIC, THE SUNSHINE LIGHT... SO I HAD TO GET RID OF WHAT I DIN'T USE BY THE SCIENTIFIC METHOD OF THROWING IT IN THE LAVATORY", - "DON'T WORRY, I REMEMBER EXACTLY HOW TO MAKE THAT BREW", - "I NEED GARLIC, BUT I ALREADY HAVE THEM. HOWEVER YOU'LL HAVE TO GET ME SOME WAX, BUBBLE GUM AND CIGARETTE PAPER OR PERHAPS A NAPKING OR SOMETHING ALIKE", - "OH...AND OF COURSE THE MOST IMPORTANT INGREDIENT. LEAVES FROM A VERY STRANGE PLANT CALLED FERNAN", - "IT'S A CLIMBING PLANT WHICH LEAVES HAVE MAGIC POWERS IF THEY'RE CUT WITH A GOLDEN SICKLE", - "SO THAT AS SOON AS YOU HAVE THESE FIVE THINGS, JUST COME HERE AND I'LL MAKE THE BREW", - "YOU'LL BE READY THEN TO FIGHT AGAINST DRASCULA", - "REMEMBER: WAX, NICOTINE, A PIECE OF BUBBLE GUM, A PAPER AND SOME FERNAN'S LEAVES CUT WITH A GOLDEN SICKLE", - "I TOLD YOU! IT WAS JUST BECAUSE OF THE BREW!", - "OH, ALL RIGHT. I'M GOING TO MAKE MYSELF A...THE BREW. JUST A MOMENT, OK?", - "IT'S A PROTECTING SPELL AGAINST VAMPIRES", - "I PUT IT THERE IN ORDER TO PRETEND THAT THE SKETCHER DIDN'T FORGET TO DRAW THE WINDOW YOU CAN SEE FROM OUTSIDE", - "ALL RIGHT, THE FIRST THING YOU MUST KNOW IS THE WAY TO DRASCULA'S CASTLE", - "THERE IS A CAVERN THAT GETS YOU STRAIGHT FROM THE CASTLE. IGOR, THE CRAZY ELVIS' FUN, TAKES IT TO GET TO THE VILLAGE EACH MORNING", - "BE CAREFUL THOUGH, THERE IS A VAMPIRE ALWAYS WATCHING OVER IT. YOU'LL HAVE TO GET RID OF HIM", - "THERE IS AN OLD WELL RIGHT BY THE CEMETERY CHURCH", - "IT WAS USED A LONG TIME AGO FOR WITCHCRAFT TRIALS", - "THEY THREW THE WITCHES IN THE WELL. IF THEY DROWNED THEY WERE REAL WITCHES. IF THEY DIDN'T, THEY WEREN'T", - "WE THREW ONE ONCE AND SHE DIDN'T DROWN, I GUESS SHE WASN'T A WITCH", - "ANYWAY. THERE IS YOUR BREW. HOWEVER, I ONLY GOT TO MAKE ENOUGH JUST FOR ONE PERSON", - "YOU'D BETTER SMOKE IT RIGHT BEFORE YOU FIGHT AGAINST DRASCULA", - "COME ON, RUN!", - "OH, JUST EXCUSES...!", - "ARE YOU JOHN HACKER? I'M DOCTOR VON BRAUN", - "LISTEN TO ME, THIS IS VERY IMPORTANT. IT'S ABOUT THE BREW", - "SHUT UP AND LET ME TALK. I JUST FOUND THIS BOOK ABOUT ANTI-VAMPIRE BREWS WARNING AGAINST MIXING THE JOINT WITH ANY ALCOHOLIC DRINK BEFORE YOU", - "ALCOHOL REACTS WHEN MIXED WITH BREW, SO THAT IT CANCELS OUT ITS EFFECTS JUST IN A FEW SECONDS", - "I'M SORRY, BUT I HAVE TO HANG UP RIGHT NOW. THE POLICE IS LOOKING FOR ME, THEY THINK I'M A PUSHER. STUPIDS!. ANYWAY, BYE AND GOOD LUCK SAVING THE WORLD!", -}, -{ - "", - "\250QUIEN DIABLOS LLAMA A ESTAS HORAS?", - "EH... NO, NO. YO SOY EL ENANO GANIMEDES... EL PROFESOR VON BRAUN YA... YA NO VIVE AQUI", - "\255NO, NO SE DONDE ESTA!", - "\255QUE TE VAYAS! ", - "IMBECIL. YA ES DEMASIADO TARDE, SIEMPRE LO ES", - "ESTOY TOTALMENTE DE ACUERDO", - "\250YO MIEDO?", - "ENTERATE CHAVAL: ESTAS HABLANDO CON EL UNICO QUE CONOCE EL SECRETO PARA ENFRENTARSE A LOS VAMPIROS", - "NO TODO EL MUNDO ES CAPAZ DE LUCHAR CON UN VAMPIRO. HAY QUE TENER UNAS CUALIDADES ESPECIALES", - "NO LAS TIENES", - "\250TE APUESTAS TODO TU DINERO A QUE NO?", - "ESTA BIEN. PASA", - "SI DE VERDAD ERES CAPAZ DE ENFRENTARTE A DRASCULA, DEBER PODER SOPORTAR TODOS LOS RUIDOS CHIRRIANTES Y VAMPIRICOS", - "\250QUEDA CLARO?", - "DE ACUERDO. ESPERA UN MOMENTO", - "POR FAVOR, PONTE EN EL CENTRO DE LA HABITACION", - "VEAMOS. \250DONDE HE PUESTO EL DISCO ESTE DE \"U\245AS ARRASCANDO UNA PIZARRA\"?", - "MUY BIEN. VAMOS ALLA", - "\250VES? ERES UN INUTIL, COMO TODOS LOS DEMAS", - "AHORA DAME EL DINERO QUE HAS PERDIDO Y VETE DE AQUI", - "Y NO VUELVAS HASTA QUE NO ESTES PREPARADO DEL TODO", - "\250Y QUE ES LO QUE QUIERES TU AHORA?", - "HE DE RECONOCERLO... TIENES APTITUDES PARA LUCHAR CON LOS VAMPIROS", - "POR CIERTO, TOMA TU DINERO. SE CUANDO ME HE EQUIVOCADO", - "AHORA VETE, QUE QUIERO DORMIR UN POCO", - "CUANDO ESTES DISPUESTO A ENFRENTARTE A ALGUN VAMPIRO, VUELVE Y TE AYUDARE EN LO QUE PUEDA", - "OH, ESO ES FACIL. LA LUZ DEL SOL O UN CRUCIFIJO Y LE HACES POLVO", - "CON EL QUE DEBES PONER ESPECIAL CUIDADO ES CON DRASCULA. SUS PODERES FRISISHNOSTICOS LE HACEN EL MAS PODEROSO DE LOS VAMPIROS", - "ESTARIAS PERDIDO A NO SER POR LA...", - "...\255POCION!", - "OH, CLARO. TIENES RAZON, SI SIGO DURMIENDO ASI A LO MEJOR TENGO PROBLEMAS DE COLUMNA CUANDO SEA VIEJO", - "BUENO, ADMITO QUE RESULTO MEJOR ADVERSARIO QUE YO, PERO MI PRINCIPAL HALLAZGO EN EL ESTUDIO DE TECNICAS ANTI-VAMPIROS FUE LO QUE ME CUBRIO LAS ESPALDAS", - "DESCUBRI UNA POCION DE INMUNIDAD. TE HACE INVULNERABLE ANTE CUALQUIER MORDEDURA DE VAMPIRO, O A SUS PODERES FRSISSHNOTICOS", - "NO, PERDONA LA TUVE EN SU DIA, PERO UNA POCION DE ESAS CARACTERISTICAS ES PELIGROSA. IMAGINATE SI CAYERA EN MANOS DE UN VAMPIRO", - "LE HARIA INMUNE A LOS AJOS, A LA LUZ DEL SOL... ASI QUE TUVE QUE DESHACERME DE LO QUE NO USE POR EL CIENTIFICO METODO DE TIRARLO A LA TAZA DEL WATER", - "TRANQUILO, ME ACUERDO PERFECTAMENTE DE COMO PREPARAR ESA POCION ", - "NECESITO AJOS, QUE DE ESO YA TENGO, PERO ME TENDRAS QUE CONSEGUIR ALGO DE CERA, NICOTINA, UN CHICLE, Y UN PAPEL DE FUMAR, O UNA SERVILLETA, O ALGO PARECIDO", - "\255AH! Y POR SUPUESTO, EL INGREDIENTE PRINCIPAL: UNAS HOJAS DE UNA EXTRA\245A PLANTA LLAMADA FERNAN", - "SE TRATA DE UNA PLANTA ENREDADERA CUYAS HOJAS PROPORCIONAN PODERES MAGICOS SI SE CORTAN CON UNA HOZ DE ORO", - "PUES YA SABES, EN CUANTO TENGAS ESAS CINCO COSAS ME LAS TRAES Y TE PREPARARE LA POCION", - "DESPUES ESTARAS LISTO PARA LUCHAR CON DRASCULA", - "RECUERDA: CERA, NICOTINA, UN CHICLE, UN PAPEL Y UNAS HOJAS DE FERNAN, LA PLANTA, CORTADAS CON UNA HOZ DE ORO", - "\255YA TE LO HE DICHO! FUE TODO GRACIAS A LA POCION", - "AH, MUY BIEN. VOY ENTONCES A PREPARARME EL PO... LA POCION. SOLO TARDO UN MOMENTO", - "ES UN SORTILEGIO DE PROTECCION CONTRA VAMPIROS", - "LO PUSE PARA DISIMULAR QUE EL DIBUJANTE SE OLVIDO DE PONER LA VENTANA QUE SE VE DESDE FUERA", - "BUENO, LO PRIMERO QUE DEBES SABER ES COMO SE VA AL CASTILLO DRASCULA", - "HAY UNA GRUTA QUE LLEVA DIRECTAMENTE AL CASTILLO Y QUE ESE LOCO FAN DE ELVIS, IGOR, USA PARA BAJAR AL PUEBLO POR LAS MA\245ANAS", - "PERO TEN CUIDADO, SIEMPRE ESTA PROTEGIDA POR UN VAMPIRO. TENDRAS QUE LIBRARTE DE EL", - "HAY UN VIEJO POZO AL LADO DE LA CAPILLA DEL CEMENTERIO", - "SE USABA ANTIGUAMENTE PARA JUZGAR CASOS DE BRUJERIA", - "SE TIRABA A LAS BRUJAS AL POZO. SI SE HUNDIAN ERAN BRUJAS. SI NO, NO", - "UNA VEZ TIRAMOS A UNA Y NO SE HUNDIO, ASI QUE NO SERIA BRUJA", - "A LO QUE VAMOS: TOMA TU POCION, PERO SOLO ME HA DADO PARA UNO", - "LO MEJOR ES QUE TE LO FUMES JUSTO ANTES DE ENFRENTARTE A DRASCULA", - "CORRE", - "\255EXCUSAS!", - "\250JOHN HACKER? SOY EL DOCTOR VON BRAUN", - "ESCUCHEME, ES MUY IMPORTANTE. ES SOBRE LA POCION", - "ME HE ENCONTRADO UN LIBRO SOBRE POCIONES Y DICE QUE NO DEBE USTED BEBER ALCOHOL UNA VEZ SE HAYA FUMADO LA POCION", - "EL ALCOHOL INGERIDO REACCIONA CON LAS SUSTANCIAS DE LA POCION Y ANULA SUS EFECTOS EN DECIMAS DE SEGUNDO", - "TENGO QUE COLGAR. LA POLICIA ME BUSCA. DICEN QUE TRAFICO CON DROGAS \255IGNORANTES! BUENO, ADIOS Y SUERTE SALVANDO AL MUNDO", -}, -{ - "WER ZUM TEUFEL KLINGELT UM DIESE UHRZEIT ?", - "aeH......NEIN, NEIN. ICH BIN HELGE SCHNEIDER...HERR PROFESSOR VON BRAUN ...aeH...WOHNT HIER NICHT MEHR", - "NEIN, ICH WEISS NICHT WO ER IST !", - "NUN GEH SCHON !", - "TROTTEL. ES IST SCHON ZU SPaeT, WIE IMMER", - "ICH BIN ABSOLUT EINVERSTANDEN", - "ICH UND DIE HOSEN VOLL ?", - "DAMIT DAS KLAR IST, KURZER : DU SPRICHST GERADE MIT DEM EINZIGEN DER DAS GEHEIMREZEPT GEGEN VAMPIRE HAT", - "NICHT JEDER KANN GEGEN EINEN VAMPIR ANTRETEN.MAN MUSS EIN PAAR GANZ BESONDERE EIGENSCHAFTEN BESITZEN", - "DU HAST SIE NICHT", - "WETTEN NICHT ? 100.000 MARK, DASS NICHT !", - "SCHON GUT, KOMM REIN", - "WENN DU DICH DRACULA WIRKLICH STELLEN WILLST WIRST DU ALLE DIESE VAMPIRTYPISCHEN SAUG-UND QUIETSCHGERaeUSCHE ERTRAGEN MueSSEN", - "IST DAS KLAR ?", - "O.K. WARTE MAL EINEN MOMENT", - "STELL DICH BITTE MAL IN DIE MITTE DES ZIMMERS", - "GUCKEN WIR MAL. WO IST DIESE PLATTE MIT\"FINGERNaeGEL KRATZEN AN DER TAFEL ENTLANG\" ?", - "SEHR GUT, GEHEN WIR DA HIN", - "SIEHST DU, DU BIST GENAUSO UNFaeHIG WIE ALLE ANDEREN !", - "JETZT GIB MIR DAS GELD,UM DAS WIR GEWETTET HABEN UND KOMM HER", - "UND KOMM ERST DANN WIEDER, WENN DU 100%IG VORBEREITET BIST", - "UND WAS WILLST DU JETZT ?", - "ICH MUSS ZUGEBEN, DASS DU DAS NoeTIGE TALENT ZUR VAMPIRJAGD HAST", - "ueBRIGENS, HIER IST DEIN GELD. ICH HABE MICH GEIRRT", - "UND JETZT GEH, ICH MoeCHTE MICH HINLEGEN", - "KOMM ZURueCK,WENN DU SO WEIT BIST, DICH EINEM VAMPIR GEGENueBERZUSTELLEN UND ICH WERDE DIR HELFEN", - "ACH, DAS IST GANZ EINFACH. EIN SONNENSTRAHL ODER EIN KRUZIFIX UND ER WIRD ZU STAUB", - "AM MEISTEN AUFPASSEN MUSST DU BEI DRASCULA..WEGEN SEINEN TRANSHYPNITISCHEN FaeHIGKEITEN IST ER DER GEFaeHRLICHSTE UNTER DEN VAMPIREN", - "DU WaeRST VERLOREN, ES SEI DENN DU HaeTTEST...", - "....DIE MISCHUNG! ", - "JA, STIMMT, DU HAST RECHT. WENN ICH WEITERHIN SO LIEGE WERDE ICH IM HOHEN ALTER WOHL RueCKENPROBLEME HABEN", - "NAJA, ICH GEBE ZU DASS ER der bessere von uns war, ABER DIE WICHTIGSTE ERKENNTNIS IN MEINEM ANTI-VAMPIR-STUDIUM WAR, MIR EINEN BODYGUARD ZUZULEGEN", - "ICH HABE EINE IMMUNITaeTSMISCHUNG GEFUNDEN. MIT DER KANN DIR KEIN EINZIGER VAMPIRBISS ETWAS ANHABEN, UND AUCH NICHT SEINE TRANSHYPNISIE.", - "NEIN, TUT MIR LEID, ICH HATTE SIE damals, ABER EINE MISCHUNG DIESER KONSISTENZ IST SEHR GEFaeHRLICH, UND STELL DIR MAL VOR, ES GERaeT IN VAMPIRHaeNDE", - "DAS WueRDE IHN IMMUN GEGEN KNOBLAUCH UND SONNENLICHT GEMACHT HABEN, DIE RESTE, DIE ICH NICHT MEHR FueR WISSENSCHAFTLICHE ZWECKE BRAUCHTE, landeten im klo", - "NUR DIE RUHE, ICH HABE DAS REZEPT KOMPLETT IM KOPF ", - "ICH BRAUCHE KNOBLAUCH,AH, HAB ICH SCHON, ABER DANN MUSST DU NOCH WACHS BESORGEN, NIKOTIN, KAUGUMMI UND EIN BLaeTTCHEN ODER EINE SERVIETTE ODER SO WAS", - "ACH KLAR ! UND DIE WICHTIGSTE ZUTAT : EIN PAAR BLaeTTER EINER SELTSAMEN PFLANZE DIE FREDDY HEISST", - "ES HANDELT SICH UM EINE TOPFBLUME DEREN BLaeTTER ZAUBERKRaeFTE HABEN, WENN MAN SIE MIT EINER GOLDSICHEL ABSCHNEIDET", - "ALSO, DU WEISST SCHON, SOBALD DU MIR DIESE FueNF ZUTATEN GEBRACHT HAST, BEREITE ICH DIR DIE MISCHUNG ZU", - "DANACH BIST DU FueR DEN KAMPF GEGEN DRASCULA GERueSTET", - "DENK DRAN : WACHS, NIKOTIN, EIN KAUGUMMI, EIN BLaeTTCHEN UND EIN PAAR BLaeTTER VON FREDDY, MIT EINER GOLDSICHEL ABGESCHNITTEN", - "HAB ICH DIR DOCH SCHON GESAGT ! NUR DANK DER MISCHUNG", - "OK. ALLES KLAR. ICH FANG DANN MAL AN EINEN ZU BAUEN...aeH VORZUBEREITEN. DAUERT AUCH NICHT LANGE", - "DAS IST EINE ZAUBERFORMEL, DIE VOR VAMPIREN SCHueTZT", - "DAS WAR ICH, DAMIT MAN NICHT MERKT, DASS DER ZEICHNER VERGESSEN HAT DAS FENSTER VON VORHIN ZU ZEICHNEN", - "ALSO, ZUERST MUSST DU WISSEN WIE MAN ZUM SCHLOSS VON DRASCULA KOMMT.", - "ES GIBT EINE GROTTE, DIE DIREKT ZUM SCHLOSS FueHRT, UND DURCH DIE IGOR, DIESER BEKLOPPTE ELVIS-FAN MORGENS IMMER ZUM DORF RUNTER GEHT", - "ABER PASS AUF, SIE WIRD PERMANENT VON EINEM VAMPIR BEWACHT, DEN DU ERSTMAL LOSWERDEN MUSST", - "ES GIBT DA EINEN ALTEN BRUNNEN BEI DER FRIEDHOFSKAPELLE", - "FRueHER WURDE ER FueR HEXENPROZESSE BENUTZT", - "MAN WARF DIE HEXEN IN DEN BRUNNEN. WENN SIE UNTERGINGEN WAREN SIE HEXEN, WENN NICHT, DANN NICHT", - "EINMAL WARFEN WIR EINE RUNTER, DIE NICHT UNTERGING, ALSO WAR SIE KEINE HEXE", - "WENN WIR LOSGEHEN, NIMMST DU DEINE MISCHUNG, ABER WIR HABEN NUR FueR EINE PERSON", - "AM BESTEN RAUCHST DU IHN DIR KURZ BEVOR DU DRACULA GEGENueBERSTEHST", - "LAUF !", - "BILLIGE AUSREDEN !", - "HEINZ HACKER ? ICH BIN DOKTOR VON BRAUN", - "HoeREN SIE ZU, ES IST SEHR WICHTIG. ES GEHT UM DIE MISCHUNG", - "ICH HABE EIN BUCH ueBER MISCHUNGEN GEFUNDEN UND DA STEHT DASS MAN KEINEN ALKOHOL TRINKEN DARF, SOBALD MAN DIE MISCHUNG GERAUCHT HAT", - "DER ALKOHOL REAGIERT IM MAGEN MIT DEN SUBSTANZEN DER MISCHUNG UND VERNICHTET IHRE WIRKUNG BINNEN WENIGER MILLISEKUNDEN", - "ICH MUSS AUFLEGEN. DIE POLIZEI IST HINTER MIR HER. DIE IDIOTEN HALTEN MICH FueR EINEN DROGEN-DEALER !ALSO, TSCHueSS UND VIEL GLueCK !", -}, -{ - "", - "QUI DIABLE APPELLE \267 CETTE HEURE-CI?", - "H... NON, NON. JE SUIS LE NAIN GANYM\324DE... LE PROFESSEUR VON BRAUN... N'HABITE DJ\267 L\267", - "NON, JE NE SAIS PAS O\353 IL EST!", - "VA-T'-EN!", - "IMBCIL! C'EST DJ\267 TROP TARD! C'EST TOUJOURS TROP TARD!", - "JE SUIS TOUT-\267-FAIT CONFORME", - "MOI PEUR?", - "RENSEIGNE-TOI, MON GARS: TU PARLES AVEC LE SEUL QUI CONNA\327T LE SECRET POUR CONFRONTER LES VAMPIRES", - "TOUT LE MONDE N'EST PAS CAPABLE DE LUTTER AVEC UN VAMPIRE. IL FAUT DES QUALITS SPCIALES", - "TU NE LES A PAS", - "EST-CE QUE TU PARIE TOUT L'ARGENT QUE TU AS \267 QUE C'EST NON?", - "\200A VA, ENTRE", - "SI EN V\220RIT\220 TU TE SENS CAPABLE DE CONFRONTER DRASCULA, IL FAUDRA QUE TU SUPPORTES TOUS LES BRUITS GRIN\200ANTS ET SU\200ANTS", - "C'EST CLAIR?", - "D'ACCORD. ATTENDS UN INSTANT", - "METS-TOI AU MILIEU DE LA CHAMBRE, S'IL TE PLA\327T", - "VOYONS! O\353 EST-CE QUE J'AI MIS LE DISQUE \"ONGLES GRATTANT UN TABLEAU\"?", - "TR\324S BIEN. ON Y VA", - "TU VOIS? TU ES UN INCAPABLE, COMME TOUS LES AUTRES", - "MAINTENANT DONNE-MOI L'ARGENT QUE TU AS PERDU ET VA-T'-EN", - "ET N'Y REVIENS \267 MOINS QUE TU SOIS COMPL\324TEMENT EN FORME", - "ET QUE VEUX-TU MAINTENANT?", - "JE DOIS LE RECONNA\327TRE... TU AS DES APTITUDES POUR LUTTER CONTRE LES VAMPIRES", - "EN FAIT, TIENS TON ARGENT. JE SAIS RECONNA\327TRE MES ERREURS", - "MAINTENANT VA-T'-EN, JE VEUX DORMIR UN PEU ", - "QUAND TU SOIS PR\322T \267 TE CONFRONTER AVEC UN VAMPIRE, REVIENS ET TU POURRAS COMPTER SUR MOI", - "OH! C'EST FACIL. AVEC LA LUMI\324RE DU SOLEIL OU UN CRUCIFIX TU LE R\220DUIT EN CENDRES", - "MAIS TU DOIS FAIRE SP\220CIALE ATTENTION AVEC DRASCULA. GR\266CE \267 SES POUVOIRS FRISYSHNOSTIQUES C'EST LE PLUS PUISSANT DES VAMPIRES", - "JE SERAIS PERDU SI CE N'EST PAS POUR LA...", - "...POTION!", - "OH, BIEN S\352R. TU AS RAISON, SI JE CONTINUE \267 DORMIR COMME \200\265, J'AURAI DES PROBL\324MES DE COLONNE DANS MA VIEILLESSE", - "bon, J'ACCEPTE QU'IL A \220T\220 MEILLEURE ADVERSAIRE QUE MOI, MAIS JE ME SUIS GARD\220 LE DOS GR\266CE \267 MA BONNE TROUVAILLE DANS L'\220TUDE DE TECHNIQUES ANTI-VAMPIRES", - "J'AI D\220COUVERT UNE POTION IMMUNOLOGIQUE QUI TE FAIT INVULN\220RABLE CONTRE N'IMPORTE QUELLE MORSURE DE VAMPIRE OU SES POUVOIRS FRSYSSHNOTIQUES", - "NON, EXCUSES-MOI. JE L'AI EUE, MAIS UNE POTION DE CES CARACT\220RISTIQUES EST DANGEREUSE. IMAGINE TOI SI ELLE TOMBAIT DANS LES MAINS D'UN VAMPIRE", - "IL DEVIENDRAIT IMMUNIS\220 AUX AILS, \267 LA LUMI\324RE DU SOLEIL. DONC, J'AI D\352 M'EN D\220BARRASSER DES EXC\220DENTS PAR LA SCIENTIFIQUE M\220THODE DE LES JETER AUX \220GOUTS", - "RESTE TRANQUILLE, JE ME SOUVIENS PARFAITEMENT DE LA PR\220PARATION DE CETTE POTION", - "il me faut D'AIL, MAIS J'EN AI D\220J\267. IL FAUDRA UN PEU DE CIRE, DE LA NICOTINE, UN CHEWING-GUM ET UN PAPIER \267 CIGARETTES, OU QUELQUE CHOSE PAREILLE", - "AH! ET CERTAINEMENT, L'INGR\220DIANT PRINCIPAL: LES FEUILLES D'UNE \220TRANGE PLANTE APPEL\220E FERNAN", - "IL S'AGIT D'UNE PLANTE GRIMPANTE DONT LES FEUILLES FOURNISSENT DES POUVOIRS MAGIQUES SI ON LES COUPE AVEC UNE FAUCILLE EN OR", - "TU LE SAIS D\220J\267. D\324S QUE TU AURAS CES CINQ TRUCS APPORTE-LES-MOI ET JE TE PR\220PARERAI LA POTION", - "APR\324S TU SERAS PR\322T POUR LUTTER CONTRE DRASCULA", - "RAPPELLE-TOI: DE LA CIRE, DE LA NICOTINE, UN CHEWING-GUM, UN PAPIER ET LES FEUILLES DE FERNAN, LA PLANTE, COUP\220ES AVEC UNE FAUCILLE EN OR", - "JE TE L'AI D\220J\267 DIT! TOUT A \220T\220 GR\266CE \267 LA POTION", - "AH! TR\324S BIEN! ALORS, JE VAIS ME PR\220PARER LE PO... LA POTION. JE N'AI QUE POUR UN MOMENT", - "C'EST UN SORTIL\324GE DE PROTECTION CONTRE-VAMPIRES", - "JE L'AI MIS POUR DISSIMULER, LE DESSINATEUR AYANT OUBLI\220 D'Y METTRE LA FEN\322TRE QU'ON VOIT DU DEHORS", - "EH BIEN, CE QUE TU DOIS SAVOIR D'ABORD C'EST LA FA\200ON D'ALLER AU CH\266TEAU DE DRASCULA", - "IL Y A UNE GROTTE QUI M\324NE DIRECTEMENT AU CH\266TEAU ET QU'IGOR, CE FOU FAN D'ELVIS, EN UTILISE POUR SE RENDRE AU VILLAGE LE MATIN", - "MAIS FAIT ATTENTION, ELLE TOUJOURS GARD\220E PAR UN VAMPIRE. TU DEVRAS T'EN D\220BARRASSER", - "IL Y A UN VIEUX PUITS \267 C\342T\220 DE LA CHAPELLE DU CIMETI\324RE", - "ON L'UTILISAIT JADIS POUR JUGER DES AFFAIRES DE SORCELLERIE", - "ON JETAIT LES SORCI\324RES AU PUITS. SI ELLES COULAIENT, ON \220TAIT S\352R; AUTREMENT, PAS", - "UNE FOIS ON A JET\220 UNE ET ELLE N'AS PAS COUL\220, DONC ELLE NE SERAIT PAS UNE SORCI\324RE", - "MAINTENANT GARDE \267 LA QUESTION QUI NOUS INT\220RESSE: TIENS TA POTION, MAIS ON NE M'A PAS DONN\220 QUE POUR UN SEULEMENT.", - "IL VAUDRA MIEUX QUE TU LA FUMES JUSTE AVANT DE CONFRONTER DRASCULA", - "COURS!", - "DES EXCUSES!", - "JHON HACKER? SUIS LE DOCTEUR VON BRAUN", - "\220COUTEZ-MOI. C'EST TR\324S IMPORTANT. C'EST SUR LA POTION", - "DANS UN LIVRE QUE J'AI TROUV\220 SUR LES POTIONS, IL DIT QUE VOUS NE DEVEZ PAS BOIR DE L'ALCOOL APR\324S AVOIR FUM\220 LA POTION ", - "L'ALCOOL AVAL\220 R\220AGIT AVEC LES INGR\220DIENTS DE LA POTION ET ANNULE SES EFFETS EN DIXI\324MES DE SECONDE", - "JE DOIS RACCROCHER. SUIS CHERCH\220 PAR LA POLICE. ILS DISENT QUE JE TRAFIQUE EN DROGUES -IGNORANTS! AU REVOIR ET BONNE CHANCE EN SAUVANT LE MONDE", -}, -{ - "", - "MA CHI BUSSA A QUESTE ORE?", - "EH...NO,NO. IO SONO IL NANNO GANIMEDI....IL PROFESSORE VON BRAUN NON ABITA QU\336 PI\353", - "NO, NON SO DOV'\324!", - "HO DETTO VIA!", - "IMBECILE. ORMAI TROPPO TARDE, SEMRE TARDE", - "SONO COMPLETAMENTE D'ACCORDO", - "IO, PAURA?", - "ASCOLTA BENE RAGAZZO: STAI PARLANDO CON L'UNICA PERSONA CHE CONOSCE IL SEGRETO PER VINCERE AI VAMPIRI", - "NON TUTTI QUANTI POSSONO LOTTARE CON UN VAMPIRO. SI DEVONO AVERE DELLE CARATTERISTICHE SPEZIALI", - "NO CE LE HAI", - "SICURO CHE NON SCOMMETI TUTTO IL TUO SOLDI!", - "VA BENE . AVANTI", - "SE DAVVERO SEI PRONTO PER LOTTARE CONTRO DRASCULA, DEVI POTERE SOPPORTARE TUTTI I RUMORI STRIDENTI E VAMPIRICI", - "TUTTO CHIARO?", - "D'ACCORDO. ASPETTA UN ATTIMO", - "PER FAVORE, METTETI NEL CENTRO DELLA CAMERA", - "DOV'\324 HO MESSO IL COMPACT DISC DI \"UNGHIE GRAFFIANDO UNA LAVAGNA\"", - "MOLTO BENE, ANDIAMO", - "VEDI? SEI UN INUTILE, COME TUTTI GLI ALTRI", - "ORA DAMI IL SOLDI CHE HAI PERSO, E VIA", - "E NON TORNARE FINO CHE NON SIA COMPLETAMENTE PRONTO", - "E COSA VUOI TU ADESSO?", - "DEVO AMMETTERLO... HAI LA STOFFA DI LOTTATORE PER VINCERE DRASCULA", - "EH..! PRENDI IL TUO SOLDI. SO QUANDO HO SBAGLIATO", - "ADESSO VATENE, VOGLIO DORMIRE UN P\343", - "QUANDO SIA DISPOSTO A UCCIDERE QUALCHE VAMPIRO, TORNA E TI AIUTER\343 ", - "QUELLO \324 FACILE. LA LUCE DEL SOLE O UN CROCIFISSO, E L'HAI SCHISCCIATO", - "CON CHI DEVI FARE MOLTA ATTENZIONE \324 CON DRASCULA. I SUOI POTERI FRISISHNOSTICI GLI FANNO IL PI\353 FORTE DEI VAMPIRI", - "NON POTREI FARE NULLA SE NON FOSSE PER LA .....", - "...POZIONE!", - "CERTO. HAI RAGIONE, SE CONTINUO DORMENDO COS\336 FORSE AVR\343 PROBLEMI DI SCHIENA QUANDO SIA VECCHIO", - "BENE, \324 VERO CHE FU MEGLIO LOTTATORE DI ME, MA IL MIO STUDIO SU TECNICHE ANTI-VAMPIRI GLI AIUT\343 MOLTISSIMO", - "HO SCOPERTO UNA POZIONE DI IMMUNUT\267 . TI FA INVULNERABILE AI MORSI DI VAMPIRI, O AI SUOI POTERI FRISISHNOTICI", - "NO, SCUSA, CE L'EBBI MOLTO TEMPO FA, MA UNA POZIONE COM'ERA LA MIA \324 PERICOLOSA. FIGURATI SE LA AVESSE UN VAMPIRO", - "GLI FAREBBE IMMUNE AGLI AGLII, ALLA LUCE DEL SOLE.... PER QUELLO L'HO SCARICATA NEL CESO", - "TRANQUILLO, MI RICORDO BENISSIMO DI COME RIFARLA", - "BISOGNO AGLII, CHE NE HO QU\326, DOVRAI PORTARMI UN P\220 DI CERA, NICOTINA, UNA GOMMA, E UNA CARTINA O UN TOVAGLIOLO, O QUALCOSA DEL GENERE", - "-AH! E COME NO, L'INGREDIENTE PRINCIPALE: DELLE FOGLIE DI UNA STRANA PIANTA CHIAMATA FERDINAN", - "\324 UNA PIANTA CONVOLVOLO, LE SUE FOGLIE PROPORZIONANO POTERI MAGICI SE SONO TAGLIATE DA UNA FALCE D'ORO", - "ALLORA, PORTAMI QUESTE CINQUE COSE E FAR\343 PER TE LA POZIONE", - "DOPO SAREI PRONTO PER UCCIDERE DRASCULA", - "RICORDA: CERA, NICOTINA, UNA GOMMA, UNA CARTINA E FOGLIE DI FERDINAN, LA PIANTA, TAGLIATE DA UNA FALCE D'ORO", - "TI L'HO GI\267 DETTO! FU TUTTO GRAZIE ALLA POZIONE", - "AH, MOLTO BENE. DUNQUE VADO A FARE LA CAN......LA POZIONE. SAR\267 UN ATTIMINO", - "\324 SOLTANTO UN SORTILEGIO DI PROTEZIONE CONTRO VAMPIRI", - "L'HO MESSO PER DISSIMULARE CHE IL DISEGNATORE HA DIMENTICATO METTERE LA FINESTRA CHE SI VEDE DA FUORI", - "BENE, PRIMA DEVI SAPERE COME ARRIVARE AL CASTELLO DRASCULA", - "C'\324 UNAGROTTA CHE VA AL CASTELLO E CHE UTILIZZA QUEL MATTO FAN DI ELVIS, IGOR, PER SCENDERE AL PAESE TUTTE LA MATTINE", - "MA FA ATTENZIONE, SEMPRE \220 PROTETTA DA UN VAMPIRO. DOVRAI LIBERARTI DI LUI", - "C'\220 UN VECCHIO POZZO ACCANTO ALLA CAPELLA DEL CIMITERO", - "SI UTILIZZAVA MOLTO TEMPO FA PER GIUDICARE CASI DI STREGONERIA", - "SI BUTTAVANO DENTRO ALLE STREGE. SE SI AFFONDAVANO ERANO STREGHE. SE NO, NO", - "UNA VOLTA BUTTAMMO UNA E GALLEGGI\220, DUNQUE NON SAREBBE UNA STREGA", - "ORA BEVE LA POZIONE. PECCATO CI SIA SOLTANTO PER UNO", - "SAR\265 MEGLIO FUMARLO PROPRIO PRIMA DELLA LOTTA CONTRO DRASCULA", - "CORRI1", - "SCUSE!", - "JOHN HACKER? SONO IL DOTTORE VON BRAUN", - "SENTA, \220 MOLTO IMPORTANTE, \220 SULLA POZIONE", - "HO TROVATO UN LIBRO SU POZIONI E DICE CHE NON SI DEVE BERE ALCOL DOPO AVERE FUMATO LA POZIONE", - "L'ALCOL BEVUTO FA REAZIONE CON LE SOSTANZE DELLA POZIONE E ANNULLA I SUOI EFFETTI IN DECIME DI SECONDO", - "DEVO RIATTACARE. LA POLIZIA MI CERCA. DICONO CHE TRAFFICO DROGHE -IGNORANTI! BENE, ALLORA ADIO E IN BOCA IL LUPO", -}, -}; - - -const char *_textsys[][4] = { -{ - "PRESS 'DEL' AGAIN TO RESTART", - "PRESS 'ESC' AGAIN TO EXIT", - "SPEECH ONLY", - "TEXT AND SPEECH", -}, -{ - "PULSA DE NUEVO SUPR PARA EMPEZAR", - "PULSA DE NUEVO ESC PARA SALIR", - "SOLO VOCES", - "VOZ Y TEXTO", -}, -{ - "BETaeTIGEN SIE ERNEUT entf UM ANZUFANGEN", - "BETaeTIGEN SIE ERNEUT ESC UM ZU BEENDEN", - "NUR STIMMEN", - "STIMME UND TEXT", -}, -{ - "APPUYEZ \267 NOUVEAU SUR SUPR POUR COMMENCER", - "APPUYEZ \267 NOUVEAU SUR ESC POUR SORTIR", - "SEULEMENT DES VOIX", - "VOIX ET TEXT", -}, -{ - "PREMI DI NUOVO SUPR PER COMINZIARE", - "PRMI DI NUOVO ESC PER USCIRE", - "SOLO SUONI", - "SUONI E TESTO", -}, -}; - - -const char *_texthis[][5] = { -{ - "", - "A long time ago, it seems that Drascula killed Von Braun's wife, and then, as he intended to face the count, Von Braun started to investigate all he found vampires.", - "When he thought he was ready, he came up to the castle and had a very violent encounter with Drascula.", - "Nobody knows exactly what happened there. Although Von Braun lost, Drascula could not kill him.", - "Von Braun felt humiliated by his defect, run away from the castle and has never dared to face Drascula ever again.", -}, -{ - "", - "", - "", - "", - "" -}, -{ - "", - "", - "", - "", - "" -}, -{ - "", - "", - "", - "", - "" -}, -{ - "", - "", - "", - "", - "" -}, -}; - - -} // End of namespace Drascula diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp index d508dc75f9..415790e67b 100644 --- a/engines/gob/coktelvideo.cpp +++ b/engines/gob/coktelvideo.cpp @@ -123,8 +123,9 @@ bool Imd::load(Common::SeekableReadStream &stream) { return false; } - _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize); - _frameLength = _soundSliceLength; + _soundSliceLength = (uint32) (((double) (1000 << 16)) / + ((double) _soundFreq / (double) _soundSliceSize)); + _frameLength = _soundSliceLength >> 16; _soundStage = 1; _hasSound = true; @@ -270,6 +271,13 @@ void Imd::disableSound() { _mixer = 0; } +bool Imd::isSoundPlaying() const { + if (_audioStream && _mixer->isSoundHandleActive(_audioHandle)) + return true; + + return false; +} + void Imd::seekFrame(int32 frame, int16 whence, bool restart) { if (!_stream) // Nothing to do @@ -318,11 +326,11 @@ void Imd::waitEndFrame() { return; if (_skipFrames == 0) { - int32 waitTime = (_curFrame * _soundSliceLength) - - (g_system->getMillis() - _soundStartTime); + int32 waitTime = (int16) (((_curFrame * _soundSliceLength) - + ((g_system->getMillis() - _soundStartTime) << 16)) >> 16); if (waitTime < 0) { - _skipFrames = -waitTime / _soundSliceLength; + _skipFrames = -waitTime / (_soundSliceLength >> 16); warning("Video A/V sync broken, skipping %d frame(s)", _skipFrames + 1); } else if (waitTime > 0) g_system->delayMillis(waitTime); @@ -333,6 +341,11 @@ void Imd::waitEndFrame() { g_system->delayMillis(_frameLength); } +void Imd::notifyPaused(uint32 duration) { + if (_soundStage == 2) + _soundStartTime += duration; +} + void Imd::copyCurrentFrame(byte *dest, uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, uint16 pitch, int16 transp) { @@ -931,10 +944,9 @@ bool Vmd::load(Common::SeekableReadStream &stream) { _soundSliceSize = -_soundSliceSize; } - _soundSliceLength = (uint16) (1000.0 / + _soundSliceLength = (uint32) (((double) (1000 << 16)) / ((double) _soundFreq / (double) _soundSliceSize)); - - _frameLength = _soundSliceLength; + _frameLength = _soundSliceLength >> 16; _soundStage = 1; _audioStream = Audio::makeAppendableAudioStream(_soundFreq, @@ -1066,8 +1078,8 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { state.flags |= kStateNoVideoData; state.left = 0x7FFF; - state.right = 0x7FFF; - state.top = 0; + state.top = 0x7FFF; + state.right = 0; state.bottom = 0; if (!_vidMem) @@ -1121,6 +1133,8 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { } else if (part.type == kPartTypeVideo) { state.flags &= ~kStateNoVideoData; + uint32 size = part.size; + // New palette if (part.flags & 2) { uint8 index = _stream->readByte(); @@ -1130,9 +1144,12 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) { _stream->skip((255 - count) * 3); state.flags |= kStatePalette; + + size -= (768 + 2); } - _stream->read(_frameData, part.size); + _stream->read(_frameData, size); + if (renderFrame(part.left, part.top, part.right, part.bottom)) { // Rendering succeeded, merging areas state.left = MIN(state.left, part.left); diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h index 4f9543e8d0..348e5e3ab1 100644 --- a/engines/gob/coktelvideo.h +++ b/engines/gob/coktelvideo.h @@ -134,11 +134,14 @@ public: /** Use an own memory block as video memory. */ virtual void setVideoMemory() = 0; - /** Play sound (if the IMD has sound). */ + /** Play sound (if the video has sound). */ virtual void enableSound(Audio::Mixer &mixer) = 0; /** Don't play sound or stop currently playing sound. */ virtual void disableSound() = 0; + /** Is sound currently playing? */ + virtual bool isSoundPlaying() const = 0; + /** Seek to a specific frame. * * @param frame The frame to which to seek. @@ -152,6 +155,9 @@ public: /** Wait for the frame to end. */ virtual void waitEndFrame() = 0; + /** Notifies the video that it was paused for duration ms. */ + virtual void notifyPaused(uint32 duration) = 0; + /** Copy the current frame. * * @param dest The memory to which to copy the current frame. @@ -184,7 +190,11 @@ public: int16 getHeight() const { return _height; } uint16 getFramesCount() const { return _framesCount; } uint16 getCurrentFrame() const { return _curFrame; } - int16 getFrameRate() const { if (_hasSound) return 1000 / _soundSliceLength; return _frameRate; } + int16 getFrameRate() const { + if (_hasSound) + return 1000 / (_soundSliceLength >> 16); + return _frameRate; + } uint32 getSyncLag() const { return _skipFrames; } const byte *getPalette() const { return _palette; } @@ -203,11 +213,15 @@ public: void enableSound(Audio::Mixer &mixer); void disableSound(); + bool isSoundPlaying() const; + void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false); State nextFrame(); void waitEndFrame(); + void notifyPaused(uint32 duration); + void copyCurrentFrame(byte *dest, uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, uint16 pitch, int16 transp = -1); @@ -250,7 +264,7 @@ protected: int16 _soundFreq; int16 _soundSliceSize; int16 _soundSlicesCount; - uint16 _soundSliceLength; + uint32 _soundSliceLength; Audio::AppendableAudioStream *_audioStream; Audio::SoundHandle _audioHandle; diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index 1fb43e96bb..8ae11b8755 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -233,8 +232,10 @@ int16 DataIO::getChunk(const char *chunkName) { if (_chunkPos[file * MAX_SLOT_COUNT + slot] == -1) break; - if (slot == MAX_SLOT_COUNT) + if (slot == MAX_SLOT_COUNT) { + warning("Chunk slots full"); return -1; + } dataDesc = _dataFiles[file]; for (int16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 7637605dcd..8351f2ecfb 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -23,7 +23,6 @@ * */ - #include "base/plugins.h" #include "common/advancedDetector.h" @@ -1685,6 +1684,71 @@ static const GOBGameDescription gameDescriptions[] = { kFeatures640, "intro" }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + EN_GRB, + kPlatformPC, + Common::ADGF_NO_FLAGS + }, + kGameTypeWoodruff, + kFeatures640, + "intro" + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + DE_DEU, + kPlatformPC, + Common::ADGF_NO_FLAGS + }, + kGameTypeWoodruff, + kFeatures640, + "intro" + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + FR_FRA, + kPlatformPC, + Common::ADGF_NO_FLAGS + }, + kGameTypeWoodruff, + kFeatures640, + "intro" + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + IT_ITA, + kPlatformPC, + Common::ADGF_NO_FLAGS + }, + kGameTypeWoodruff, + kFeatures640, + "intro" + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + ES_ESP, + kPlatformPC, + Common::ADGF_NO_FLAGS + }, + kGameTypeWoodruff, + kFeatures640, + "intro" + }, { { "dynasty", diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index 2a4732954c..8a7de9bdaa 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 959a064b7d..b5bc56b6f5 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/cursorman.h" @@ -31,9 +30,10 @@ #include "gob/draw.h" #include "gob/global.h" #include "gob/util.h" -#include "gob/cdrom.h" #include "gob/game.h" #include "gob/scenery.h" +#include "gob/inter.h" +#include "gob/sound/sound.h" namespace Gob { @@ -170,7 +170,7 @@ void Draw_v1::printTotText(int16 id) { int16 spriteRight, spriteBottom; char buf[20]; - _vm->_cdrom->playMultMusic(); + _vm->_sound->cdPlayMultMusic(); if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr) return; diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 8f7d5b325b..378ff0dcdf 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/cursorman.h" @@ -33,6 +32,7 @@ #include "gob/util.h" #include "gob/game.h" #include "gob/scenery.h" +#include "gob/inter.h" #include "gob/video.h" namespace Gob { @@ -178,13 +178,13 @@ void Draw_v2::animateCursor(int16 cursor) { _vm->_util->delay(5); } } - } else + } else { blitCursor(); + _cursorX = newX; + _cursorY = newY; + } _showCursor &= ~1; - - _cursorX = newX; - _cursorY = newY; } void Draw_v2::printTotText(int16 id) { @@ -246,22 +246,29 @@ void Draw_v2::printTotText(int16 id) { } if (_renderFlags & RENDERFLAG_FROMSPLIT) { - destY = _vm->_video->_splitStart; + int16 start; + + start = _vm->_video->_splitStart; + + destY = start; spriteBottom = READ_LE_UINT16(ptr + 6) - READ_LE_UINT16(ptr + 2); + if (_renderFlags & RENDERFLAG_DOUBLECOORDS) spriteBottom *= 3; - spriteBottom += _vm->_video->_splitStart; + + spriteBottom += start; + if (_renderFlags & RENDERFLAG_DOUBLECOORDS) { - spriteBottom += _backDeltaX; - destY += _backDeltaX; + spriteBottom += _backDeltaY; + destY += _backDeltaY; } } else { + destY = READ_LE_UINT16(ptr + 2); + spriteBottom = READ_LE_UINT16(ptr + 6); + if (_renderFlags & RENDERFLAG_DOUBLECOORDS) { - destY = READ_LE_UINT16(ptr + 2) * 2; - spriteBottom = READ_LE_UINT16(ptr + 6) * 2; - } else { - destY = READ_LE_UINT16(ptr + 2); - spriteBottom = READ_LE_UINT16(ptr + 6); + destY *= 2; + spriteBottom *= 2; } } @@ -629,8 +636,7 @@ void Draw_v2::spriteOperation(int16 operation) { _destSpriteX += _backDeltaX; _destSpriteY += _backDeltaY; if ((operation == DRAW_DRAWLINE) || - ((operation >= DRAW_DRAWBAR) && - (operation <= DRAW_FILLRECTABS))) { + ((operation >= DRAW_DRAWBAR) && (operation <= DRAW_FILLRECTABS))) { _spriteRight += _backDeltaX; _spriteBottom += _backDeltaY; } @@ -646,6 +652,24 @@ void Draw_v2::spriteOperation(int16 operation) { int16 destSurface = _destSurface; int16 sourceSurface = _sourceSurface; + if (_vm->_video->_splitSurf && ((_destSurface == 20) || (_destSurface == 21))) { + if ((_destSpriteY >= _vm->_video->_splitStart)) { + _destSpriteY -= _vm->_video->_splitStart; + if ((operation == DRAW_DRAWLINE) || + ((operation >= DRAW_DRAWBAR) && (operation <= DRAW_FILLRECTABS))) + _spriteBottom -= _vm->_video->_splitStart; + + _destSurface += 4; + } + + if ((_spriteTop >= _vm->_video->_splitStart) && (operation == DRAW_BLITSURF)) { + _spriteTop -= _vm->_video->_splitStart; + if (_destSurface < 24) + _destSurface += 4; + } + + } + adjustCoords(0, &_destSpriteX, &_destSpriteY); if ((operation != DRAW_LOADSPRITE) && (_needAdjust != 2)) { adjustCoords(0, &_spriteRight, &_spriteBottom); diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp index 08235f16e2..f68ce47783 100644 --- a/engines/gob/driver_vga.cpp +++ b/engines/gob/driver_vga.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/primitives.h" @@ -110,10 +109,16 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, int16 width = MIN((right - left) + 1, (int) dest->getWidth()); int16 height = MIN((bottom - top) + 1, (int) dest->getHeight()); + if ((width < 1) || (height < 1)) + return; + byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left; byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x; + uint32 size = width * height; + if (transp) { + while (height--) { for (int16 i = 0; i < width; ++i) { if (srcPos[i]) @@ -123,13 +128,26 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, srcPos += source->getWidth(); destPos += dest->getWidth(); } + + } else if (((srcPos >= destPos) && (srcPos <= (destPos + size))) || + ((destPos >= srcPos) && (destPos <= (srcPos + size)))) { + + while (height--) { + memmove(destPos, srcPos, width); + + srcPos += source->getWidth(); + destPos += dest->getWidth(); + } + } else { + while (height--) { memcpy(destPos, srcPos, width); srcPos += source->getWidth(); destPos += dest->getWidth(); } + } } diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index 666f46fde1..73fa820fa0 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -35,7 +34,7 @@ #include "gob/parse.h" #include "gob/draw.h" #include "gob/mult.h" -#include "gob/music.h" +#include "gob/sound/sound.h" namespace Gob { @@ -60,9 +59,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { _collStackElemSizes[i] = 0; } - _infIns = 0; - _infogrames = 0; - _curTotFile[0] = 0; _curExtFile[0] = 0; _totToLoad[0] = 0; @@ -105,10 +101,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { } Game::~Game() { - delete _infIns; - - for (int i = 0; i < 60; i++) - _soundSamples[i].free(); } byte *Game::loadExtData(int16 itemId, int16 *pResWidth, @@ -295,16 +287,7 @@ void Game::freeSoundSlot(int16 slot) { if (slot == -1) slot = _vm->_parse->parseValExpr(); - if ((slot < 0) || (slot >= 60) || _soundSamples[slot].empty()) - return; - - SoundDesc &sample = _soundSamples[slot]; - - if (sample.getType() == SOUND_ADL) - if (_vm->_adlib && (_vm->_adlib->getIndex() == slot)) - _vm->_adlib->stopPlay(); - - _vm->_snd->freeSample(sample); + _vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot)); } void Game::evaluateScroll(int16 x, int16 y) { @@ -367,7 +350,7 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, _vm->_util->processInput(true); - if (_vm->_mult->_multData && _vm->_global->_inter_variables && + if (_vm->_mult->_multData && _vm->_inter->_variables && (VAR(58) != 0)) { if (_vm->_mult->_multData->frameStart != (int) VAR(58) - 1) _vm->_mult->_multData->frameStart++; @@ -380,7 +363,7 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, if ((_vm->_inter->_soundEndTimeKey != 0) && (_vm->_util->getTimeKey() >= _vm->_inter->_soundEndTimeKey)) { - _vm->_snd->stopSound(_vm->_inter->_soundStopVal); + _vm->_sound->blasterStop(_vm->_inter->_soundStopVal); _vm->_inter->_soundEndTimeKey = 0; } @@ -497,8 +480,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { _extTableArray[_backupedCount] = _extTable; _extHandleArray[_backupedCount] = _extHandle; _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_global->_inter_variables; - _variablesSizesArray[_backupedCount] = _vm->_global->_inter_variablesSizes; + _variablesArray[_backupedCount] = _vm->_inter->_variables; strcpy(_curTotFileArray[_backupedCount], _curTotFile); curBackupPos = _curBackupPos; @@ -508,10 +490,8 @@ void Game::totSub(int8 flags, const char *newTotFile) { _totTextData = 0; _totFileData = 0; _totResourceTable = 0; - if (flags & 1) { - _vm->_global->_inter_variables = 0; - _vm->_global->_inter_variablesSizes = 0; - } + if (flags & 1) + _vm->_inter->_variables = 0; strncpy0(_curTotFile, newTotFile, 9); strcat(_curTotFile, ".TOT"); @@ -531,9 +511,8 @@ void Game::totSub(int8 flags, const char *newTotFile) { popCollisions(); - if ((flags & 1) && _vm->_global->_inter_variables) { - delete[] _vm->_global->_inter_variables; - delete[] _vm->_global->_inter_variablesSizes; + if ((flags & 1) && _vm->_inter->_variables) { + _vm->_inter->delocateVars(); } _backupedCount--; @@ -547,8 +526,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { _extTable = _extTableArray[_backupedCount]; _extHandle = _extHandleArray[_backupedCount]; _imFileData = _imFileDataArray[_backupedCount]; - _vm->_global->_inter_variables = _variablesArray[_backupedCount]; - _vm->_global->_inter_variablesSizes = _variablesSizesArray[_backupedCount]; + _vm->_inter->_variables = _variablesArray[_backupedCount]; strcpy(_curTotFile, _curTotFileArray[_backupedCount]); strcpy(_curExtFile, _curTotFile); _curExtFile[strlen(_curExtFile) - 4] = '\0'; @@ -580,8 +558,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { _extTableArray[_backupedCount] = _extTable; _extHandleArray[_backupedCount] = _extHandle; _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_global->_inter_variables; - _variablesSizesArray[_backupedCount] = _vm->_global->_inter_variablesSizes; + _variablesArray[_backupedCount] = _vm->_inter->_variables; strcpy(_curTotFileArray[_backupedCount], _curTotFile); _backupedCount++; } @@ -597,8 +574,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { _imFileData = _imFileDataArray[_curBackupPos]; _extTable = _extTableArray[_curBackupPos]; _extHandle = _extHandleArray[_curBackupPos]; - _vm->_global->_inter_variables = _variablesArray[_curBackupPos]; - _vm->_global->_inter_variablesSizes = _variablesSizesArray[_curBackupPos]; + _vm->_inter->_variables = _variablesArray[_curBackupPos]; strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); strcpy(_curExtFile, _curTotFile); _curExtFile[strlen(_curExtFile) - 4] = '\0'; @@ -625,8 +601,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { _extTable = _extTableArray[_curBackupPos]; _extHandle = _extHandleArray[_curBackupPos]; _imFileData = _imFileDataArray[_curBackupPos]; - _vm->_global->_inter_variables = _variablesArray[_curBackupPos]; - _vm->_global->_inter_variablesSizes = _variablesSizesArray[_curBackupPos]; + _vm->_inter->_variables = _variablesArray[_curBackupPos]; strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); strcpy(_curExtFile, _curTotFile); _curExtFile[strlen(_curExtFile) - 4] = '\0'; diff --git a/engines/gob/game.h b/engines/gob/game.h index 5cf5e1bea6..15f6ab963a 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -26,9 +26,7 @@ #ifndef GOB_GAME_H #define GOB_GAME_H -#include "sound/mods/infogrames.h" - -#include "gob/sound.h" +#include "gob/variables.h" namespace Gob { @@ -119,12 +117,6 @@ public: int16 _extHandle; - SoundDesc _soundSamples[60]; - - Audio::Infogrames::Instruments *_infIns; - Audio::Infogrames *_infogrames; - Audio::SoundHandle _infHandle; - char _totToLoad[20]; int32 _startTimeKey; @@ -210,9 +202,8 @@ protected: ExtTable *_extTableArray[5]; int16 _extHandleArray[5]; byte *_imFileDataArray[5]; - byte *_variablesArray[5]; + Variables *_variablesArray[5]; char _curTotFileArray[5][14]; - byte *_variablesSizesArray[5]; GobEngine *_vm; diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index e9e37a027b..66deea8ec4 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" @@ -32,15 +31,13 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/music.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/inter.h" #include "gob/mult.h" #include "gob/video.h" #include "gob/parse.h" -#include "gob/sound.h" #include "gob/scenery.h" +#include "gob/sound/sound.h" namespace Gob { @@ -74,11 +71,11 @@ void Game_v1::playTot(int16 skipPlay) { _vm->_draw->_fontToSprite[i].height = -1; } - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); - } else - _vm->_cdrom->stopPlaying(); + if (_vm->getPlatform() == Common::kPlatformMacintosh) + _vm->_sound->adlibStop(); + else + _vm->_sound->cdStop(); + _vm->_draw->animateCursor(4); _vm->_inter->initControlVars(1); _vm->_mult->initAll(); @@ -169,12 +166,8 @@ void Game_v1::playTot(int16 skipPlay) { _vm->_global->_inter_animDataSize = READ_LE_UINT16(_totFileData + 0x38); - if (!_vm->_global->_inter_variables) { - variablesCount = READ_LE_UINT16(_totFileData + 0x2C); - _vm->_global->_inter_variables = new byte[variablesCount * 4]; - _vm->_global->_inter_variablesSizes = new byte[variablesCount * 4]; - _vm->_global->clearVars(variablesCount); - } + if (!_vm->_inter->_variables) + _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C)); _vm->_global->_inter_execPtr = _totFileData; _vm->_global->_inter_execPtr += READ_LE_UINT32(_totFileData + 0x64); @@ -229,7 +222,7 @@ void Game_v1::playTot(int16 skipPlay) { for (int i = 0; i < SPRITES_COUNT; i++) _vm->_draw->freeSprite(i); - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); for (int i = 0; i < 20; i++) freeSoundSlot(i); diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index 45542541e3..adf75176ab 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" @@ -38,9 +37,9 @@ #include "gob/mult.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -55,7 +54,6 @@ void Game_v2::playTot(int16 skipPlay) { int16 _captureCounter; int16 breakFrom; int16 nestLevel; - int32 variablesCount; int32 totSize; byte *filePtr; byte *savedIP; @@ -73,7 +71,7 @@ void Game_v2::playTot(int16 skipPlay) { if (skipPlay <= 0) { while (!_vm->_quitRequested) { - if (_vm->_global->_inter_variables) + if (_vm->_inter->_variables) _vm->_draw->animateCursor(4); if (skipPlay != -1) { @@ -205,12 +203,8 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_global->_inter_animDataSize = READ_LE_UINT16(_totFileData + 0x38); - if (!_vm->_global->_inter_variables) { - variablesCount = READ_LE_UINT16(_totFileData + 0x2C); - _vm->_global->_inter_variables = new byte[variablesCount * 4]; - _vm->_global->_inter_variablesSizes = new byte[variablesCount * 4]; - _vm->_global->clearVars(variablesCount); - } + if (!_vm->_inter->_variables) + _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C)); _vm->_global->_inter_execPtr = _totFileData; _vm->_global->_inter_execPtr += @@ -265,11 +259,14 @@ void Game_v2::playTot(int16 skipPlay) { if (skipPlay != -1) { _vm->_goblin->freeObjects(); - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); + + for (int i = 0; i < Sound::kSoundsCount; i++) { + SoundDesc *sound = _vm->_sound->sampleGetBySlot(i); - for (int i = 0; i < 60; i++) - if (_soundSamples[i].getType() == SOUND_SND) - _vm->_snd->freeSample(_soundSamples[i]); + if (sound && (sound->getType() == SOUND_SND)) + _vm->_sound->sampleFree(sound); + } } _vm->_vidPlayer->primaryClose(); @@ -630,13 +627,15 @@ void Game_v2::collisionsBlock(void) { Collision *collArea; int16 timeKey; byte *savedIP; + byte collAreaStart; if (_shouldPushColls) pushCollisions(0); - collArea = _collisionAreas; - while (collArea->left != 0xFFFF) - collArea++; + collAreaStart = 0; + while (_collisionAreas[collAreaStart].left != 0xFFFF) + collAreaStart++; + collArea = &_collisionAreas[collAreaStart]; _shouldPushColls = 0; collResId = -1; @@ -962,7 +961,7 @@ void Game_v2::collisionsBlock(void) { continue; _activeCollResId = collPtr->id; - _activeCollIndex = i; + _activeCollIndex = i + collAreaStart; _vm->_inter->storeMouse(); if (VAR(16) != 0) break; @@ -1004,7 +1003,7 @@ void Game_v2::collisionsBlock(void) { if ((collPtr->id & 0xF000) == 0x8000) if (++counter == descIndex) { _activeCollResId = collPtr->id; - _activeCollIndex = i; + _activeCollIndex = i + collAreaStart; break; } } @@ -1404,7 +1403,7 @@ int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, flag = 1; - if (_vm->_global->_inter_variables) + if (_vm->_inter->_variables) WRITE_VAR(56, pos); while (1) { diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index 1445601017..acca5564dd 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -123,8 +123,6 @@ Global::Global(GobEngine *vm) : _vm(vm) { _inter_resStr[0] = 0; _inter_resVal = 0; - _inter_variablesSizes = 0; - _inter_variables = 0; _inter_execPtr = 0; _inter_animDataSize = 10; diff --git a/engines/gob/global.h b/engines/gob/global.h index 45c179d277..32651cf15d 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -123,8 +123,6 @@ public: char _inter_resStr[200]; int32 _inter_resVal; - byte *_inter_variablesSizes; // 0: single byte, 1: two bytes, 3: four bytes - byte *_inter_variables; byte *_inter_execPtr; int16 _inter_animDataSize; @@ -134,73 +132,11 @@ public: // Can be 1, 2 or 3 for normal, double and triple speed, respectively uint8 _speedFactor; - void clearVars(uint32 count) { - uint32 size = count * 4; - - memset(_inter_variables, 0, size); - memset(_inter_variablesSizes, 0, size); - for (uint32 i = 0; i < size; i += 4) - _inter_variablesSizes[i] = 3; - } - - void writeVarSizeStr(uint32 offset, uint32 len) { - uint32 i; - uint32 inVar; - uint32 varOff; - - inVar = offset % 4; - varOff = (offset >> 2) << 2; - for (i = 0; i < 4; i++) { - if (_inter_variablesSizes[varOff + i] == 3) - _inter_variablesSizes[varOff + i] = 0; - else if ((inVar == (i+1)) && (_inter_variablesSizes[varOff + i] == 1)) - _inter_variablesSizes[varOff + i] = 0; - } - memset(_inter_variablesSizes + offset, 0, len); - } - - void writeVar(uint32 offset, uint32 val) { - WRITE_UINT32(_inter_variables + offset, val); - writeVarSize(offset, 3); - } - void writeVar(uint32 offset, uint16 val) { - WRITE_UINT16(_inter_variables + offset, val); - writeVarSize(offset, 1); - } - void writeVar(uint32 offset, uint8 val) { - (*(uint8 *)(_inter_variables + offset)) = val; - writeVarSize(offset, 0); - } - void writeVar(uint32 offset, const char *str) { - writeVarSizeStr(offset, strlen(str)); - strcpy((char *) (_inter_variables + offset), str); - } - Global(GobEngine *vm); ~Global(); protected: GobEngine *_vm; - - void writeVarSize(uint32 offset, byte n) { - uint32 i; - uint32 inVar; - uint32 varOff; - - inVar = offset % 4; - varOff = (offset >> 2) << 2; - for (i = 0; i < 4; i++) { - if (_inter_variablesSizes[varOff + i] == 3) - _inter_variablesSizes[varOff + i] = 0; - else if ((inVar == (i+1)) && (_inter_variablesSizes[varOff + i] == 1)) - _inter_variablesSizes[varOff + i] = 0; - } - - _inter_variablesSizes[offset] = n; - for (; n > 0; n--) - _inter_variablesSizes[offset + n] = 0; - } - }; } // End of namespace Gob diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 863665357b..a3fe0ebbe2 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/events.h" @@ -37,18 +36,16 @@ #include "gob/util.h" #include "gob/dataio.h" #include "gob/game.h" -#include "gob/sound.h" +#include "gob/sound/sound.h" #include "gob/init.h" #include "gob/inter.h" #include "gob/draw.h" -#include "gob/cdrom.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" #include "gob/palanim.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/music.h" #include "gob/videoplayer.h" #include "gob/saveload.h" @@ -71,13 +68,14 @@ const Common::Language GobEngine::_gobToScummVMLang[] = { GobEngine::GobEngine(OSystem *syst) : Engine(syst) { _vm = this; - _snd = 0; _adlib = 0; _mult = 0; - _game = 0; _global = 0; _cdrom = 0; - _dataIO = 0; _goblin = 0; _vidPlayer = 0; - _init = 0; _inter = 0; _map = 0; - _palAnim = 0; _parse = 0; _scenery = 0; - _draw = 0; _util = 0; _video = 0; - _saveLoad = 0; + _sound = 0; _mult = 0; _game = 0; + _global = 0; _dataIO = 0; _goblin = 0; + _vidPlayer = 0; _init = 0; _inter = 0; + _map = 0; _palAnim = 0; _parse = 0; + _scenery = 0; _draw = 0; _util = 0; + _video = 0; _saveLoad = 0; + + _pauseStart = 0; // Setup mixer _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); @@ -89,21 +87,24 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { Common::addSpecialDebugLevel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level"); Common::addSpecialDebugLevel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level"); Common::addSpecialDebugLevel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level"); - Common::addSpecialDebugLevel(kDebugMusic, "Music", "CD, Adlib and Infogrames music debug level"); + Common::addSpecialDebugLevel(kDebugSound, "Sound", "Sound output debug level"); Common::addSpecialDebugLevel(kDebugParser, "Parser", "Parser debug level"); Common::addSpecialDebugLevel(kDebugGameFlow, "Gameflow", "Gameflow debug level"); Common::addSpecialDebugLevel(kDebugFileIO, "FileIO", "File Input/Output debug level"); + Common::addSpecialDebugLevel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); Common::addSpecialDebugLevel(kDebugGraphics, "Graphics", "Graphics debug level"); + Common::addSpecialDebugLevel(kDebugVideo, "Video", "IMD/VMD video debug level"); Common::addSpecialDebugLevel(kDebugCollisions, "Collisions", "Collisions debug level"); syst->getEventManager()->registerRandomSource(_rnd, "gob"); } GobEngine::~GobEngine() { + deinitGameParts(); + // Stop all mixer streams (except for the permanent ones). _vm->_mixer->stopAll(); - deinitGameParts(); delete[] _startTot; delete[] _startTot0; } @@ -118,6 +119,12 @@ void GobEngine::shutdown() { _quitRequested = true; } +const char *GobEngine::getLangDesc(int16 language) const { + if ((language < 0) || (language > 8)) + language = 2; + return Common::getLanguageDescription(_gobToScummVMLang[language]); +} + void GobEngine::validateLanguage() { if (_vm->_global->_languageWanted != _vm->_global->_language) { warning("Your game version doesn't support the requested language %s", @@ -140,6 +147,30 @@ void GobEngine::validateVideoMode(int16 videoMode) { error("Video mode 0x%X is not supported!", videoMode); } +Common::Platform GobEngine::getPlatform() const { + return _platform; +} + +GameType GobEngine::getGameType() const { + return _gameType; +} + +bool GobEngine::isCD() const { + return (_features & kFeaturesCD) != 0; +} + +bool GobEngine::isEGA() const { + return (_features & kFeaturesEGA) != 0; +} + +bool GobEngine::is640() const { + return (_features & kFeatures640) != 0; +} + +bool GobEngine::hasAdlib() const { + return (_features & kFeaturesAdlib) != 0; +} + int GobEngine::init() { if (!initGameParts()) { GUIErrorMessage("GobEngine::init(): Unknown version of game engine"); @@ -219,8 +250,26 @@ int GobEngine::init() { return 0; } +void GobEngine::pauseEngineIntern(bool pause) { + if (pause) { + _pauseStart = _system->getMillis(); + } else { + uint32 duration = _system->getMillis() - _pauseStart; + + _vm->_vidPlayer->notifyPaused(duration); + + _vm->_game->_startTimeKey += duration; + _vm->_draw->_cursorTimeKey += duration; + if (_vm->_inter->_soundEndTimeKey != 0) + _vm->_inter->_soundEndTimeKey += duration; + } + + _mixer->pauseAll(pause); +} + bool GobEngine::initGameParts() { - _adlib = 0; + _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; + _saveLoad = 0; _global = new Global(this); @@ -228,8 +277,7 @@ bool GobEngine::initGameParts() { _dataIO = new DataIO(this); _palAnim = new PalAnim(this); _vidPlayer = new VideoPlayer(this); - _cdrom = new CDROM(this); - _snd = new Snd(this); + _sound = new Sound(this); switch (_gameType) { case kGameTypeGob1: @@ -327,7 +375,7 @@ bool GobEngine::initGameParts() { _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); - _saveLoad = new SaveLoad_v3(this, _targetName.c_str()); + _saveLoad = new SaveLoad_v4(this, _targetName.c_str()); break; default: @@ -336,10 +384,6 @@ bool GobEngine::initGameParts() { break; } - _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; - if (!_noMusic && hasAdlib()) - _adlib = new Adlib(this); - if (is640()) { _video->_surfWidth = _width = 640; _video->_surfHeight = _video->_splitHeight1 = _height = 480; @@ -360,15 +404,12 @@ bool GobEngine::initGameParts() { } void GobEngine::deinitGameParts() { - delete _snd; _snd = 0; - delete _adlib; _adlib = 0; + delete _saveLoad; _saveLoad = 0; delete _mult; _mult = 0; + delete _vidPlayer; _vidPlayer = 0; delete _game; _game = 0; delete _global; _global = 0; - delete _cdrom; _cdrom = 0; - delete _dataIO; _dataIO = 0; delete _goblin; _goblin = 0; - delete _vidPlayer; _vidPlayer = 0; delete _init; _init = 0; delete _inter; _inter = 0; delete _map; _map = 0; @@ -378,7 +419,8 @@ void GobEngine::deinitGameParts() { delete _draw; _draw = 0; delete _util; _util = 0; delete _video; _video = 0; - delete _saveLoad; _saveLoad = 0; + delete _sound; _sound = 0; + delete _dataIO; _dataIO = 0; } } // End of namespace Gob diff --git a/engines/gob/gob.h b/engines/gob/gob.h index e23e917a7c..ae2b53bc31 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -35,11 +35,10 @@ namespace Gob { class Game; -class Snd; +class Sound; class Video; class Global; class Draw; -class CDROM; class DataIO; class Goblin; class VideoPlayer; @@ -52,31 +51,33 @@ class Parse; class Scenery; class Util; class SaveLoad; -class Adlib; - -#define VARP(offs) (_vm->_global->_inter_variables + (offs)) -#define WRITE_VARO_UINT32(offs, val) _vm->_global->writeVar(offs, (uint32) (val)) -#define WRITE_VARO_UINT16(offs, val) _vm->_global->writeVar(offs, (uint16) (val)) -#define WRITE_VARO_UINT8(offs, val) _vm->_global->writeVar(offs, (uint8) (val)) -#define WRITE_VARO_STR(offs, str) _vm->_global->writeVar(offs, (const char *) (str)) -#define WRITE_VAR_UINT32(var, val) WRITE_VARO_UINT32((var) << 2, (val)) -#define WRITE_VAR_UINT16(var, val) WRITE_VARO_UINT16((var) << 2, (val)) -#define WRITE_VAR_UINT8(var, val) WRITE_VARO_UINT8((var) << 2, (val)) -#define WRITE_VAR_STR(var, str) WRITE_VARO_STR((var) << 2, (str)) -#define READ_VARO_UINT32(offs) READ_UINT32(VARP(offs)) -#define READ_VARO_UINT16(offs) READ_UINT16(VARP(offs)) -#define READ_VARO_UINT8(offs) (*((uint8 *) VARP(offs))) -#define READ_VAR_UINT32(var) READ_VARO_UINT32((var) << 2) -#define READ_VAR_UINT16(var) READ_VARO_UINT16((var) << 2) -#define READ_VAR_UINT8(var) READ_VARO_UINT8((var) << 2) -#define GET_VARO_STR(offs) ((char *) VARP(offs)) -#define GET_VAR_STR(var) GET_VARO_STR((var) << 2) - -#define WRITE_VAR_OFFSET(offs, val) WRITE_VARO_UINT32((offs), (val)) -#define WRITE_VAR(var, val) WRITE_VAR_UINT32((var), (val)) -#define VAR_OFFSET(offs) READ_VARO_UINT32(offs) -#define VAR(var) READ_VAR_UINT32(var) -#define VAR_ADDRESS(var) ((uint32 *) VARP((var) << 2)) + +#define WRITE_VAR_UINT32(var, val) _vm->_inter->_variables->writeVar32(var, val) +#define WRITE_VAR_UINT16(var, val) _vm->_inter->_variables->writeVar16(var, val) +#define WRITE_VAR_UINT8(var, val) _vm->_inter->_variables->writeVar8(var, val) +#define WRITE_VAR_STR(var, str) _vm->_inter->_variables->writeVarString(var, str) +#define WRITE_VARO_UINT32(off, val) _vm->_inter->_variables->writeOff32(off, val) +#define WRITE_VARO_UINT16(off, val) _vm->_inter->_variables->writeOff16(off, val) +#define WRITE_VARO_UINT8(off, val) _vm->_inter->_variables->writeOff8(off, val) +#define WRITE_VARO_STR(off, str) _vm->_inter->_variables->writeOffString(off, str) +#define READ_VAR_UINT32(var) _vm->_inter->_variables->readVar32(var) +#define READ_VAR_UINT16(var) _vm->_inter->_variables->readVar16(var) +#define READ_VAR_UINT8(var) _vm->_inter->_variables->readVar8(var) +#define READ_VARO_UINT32(off) _vm->_inter->_variables->readOff32(off) +#define READ_VARO_UINT16(off) _vm->_inter->_variables->readOff16(off) +#define READ_VARO_UINT8(off) _vm->_inter->_variables->readOff8(off) +#define GET_VAR_STR(var) _vm->_inter->_variables->getAddressVarString(var, 0) +#define GET_VARO_STR(off) _vm->_inter->_variables->getAddressOffString(off, 0) +#define GET_VAR_FSTR(var) _vm->_inter->_variables->getAddressVarString(var) +#define GET_VARO_FSTR(off) _vm->_inter->_variables->getAddressOffString(off) + +#define VAR_ADDRESS(var) _vm->_inter->_variables->getAddressVar32(var) + +#define WRITE_VAR_OFFSET(off, val) WRITE_VARO_UINT32((off), (val)) +#define WRITE_VAR(var, val) WRITE_VAR_UINT32((var), (val)) +#define VAR_OFFSET(off) READ_VARO_UINT32(off) +#define VAR(var) READ_VAR_UINT32(var) + enum GameType { kGameTypeNone = 0, @@ -102,12 +103,14 @@ enum { kDebugFuncOp = 1 << 0, kDebugDrawOp = 1 << 1, kDebugGobOp = 1 << 2, - kDebugMusic = 1 << 3, // CD, Adlib and Infogrames music + kDebugSound = 1 << 3, kDebugParser = 1 << 4, kDebugGameFlow = 1 << 5, kDebugFileIO = 1 << 6, - kDebugGraphics = 1 << 7, - kDebugCollisions = 1 << 8 + kDebugSaveLoad = 1 << 7, + kDebugGraphics = 1 << 8, + kDebugVideo = 1 << 9, + kDebugCollisions = 1 << 10 }; inline char *strncpy0(char *dest, const char *src, size_t n) { @@ -171,12 +174,19 @@ private: struct GOBGameDescription; class GobEngine : public Engine { -protected: +private: GobEngine *_vm; + GameType _gameType; + int32 _features; + Common::Platform _platform; + + uint32 _pauseStart; + int go(); int init(); + void pauseEngineIntern(bool pause); bool initGameParts(); void deinitGameParts(); @@ -185,11 +195,7 @@ public: Common::RandomSource _rnd; - GameType _gameType; - int32 _features; Common::Language _language; - Common::Platform _platform; - uint16 _width; uint16 _height; uint8 _mode; @@ -204,10 +210,9 @@ public: Util *_util; DataIO *_dataIO; Game *_game; - Snd *_snd; + Sound *_sound; Video *_video; Draw *_draw; - CDROM *_cdrom; Goblin *_goblin; Init *_init; Map *_map; @@ -217,24 +222,20 @@ public: Scenery *_scenery; Inter *_inter; SaveLoad *_saveLoad; - Adlib *_adlib; VideoPlayer *_vidPlayer; void shutdown(); - const char *getLangDesc(int16 language) { - if ((language < 0) || (language > 8)) - language = 2; - return Common::getLanguageDescription(_gobToScummVMLang[language]); - } + const char *getLangDesc(int16 language) const; void validateLanguage(); void validateVideoMode(int16 videoMode); - GameType getGameType() { return _gameType; } - bool isCD() { return (_features & kFeaturesCD) != 0; } - bool isEGA() { return (_features & kFeaturesEGA) != 0; } - bool is640() { return (_features & kFeatures640) != 0; } - bool hasAdlib() { return (_features & kFeaturesAdlib) != 0; } + Common::Platform getPlatform() const; + GameType getGameType() const; + bool isCD() const; + bool isEGA() const; + bool is640() const; + bool hasAdlib() const; GobEngine(OSystem *syst); virtual ~GobEngine(); diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index 64a2b15ef4..e7aed0790e 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -32,7 +32,8 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/scenery.h" -#include "gob/sound.h" +#include "gob/inter.h" +#include "gob/sound/sound.h" namespace Gob { @@ -164,7 +165,7 @@ Goblin::~Goblin() { for (col = 0; col < 6; col++) if (_goblins[i]->realStateMach[state][col]) delete _goblins[i]->realStateMach[state][col]; - delete []_goblins[i]->realStateMach; + delete[] _goblins[i]->realStateMach; } delete _goblins[i]; } @@ -176,7 +177,7 @@ Goblin::~Goblin() { for (col = 0; col < 6; col++) if (_objects[i]->realStateMach[state][col]) delete _objects[i]->realStateMach[state][col]; - delete []_objects[i]->realStateMach; + delete[] _objects[i]->realStateMach; } delete _objects[i]; } @@ -255,8 +256,8 @@ void Goblin::sortByOrder(Util::List *list) { void Goblin::playSound(SoundDesc &snd, int16 repCount, int16 freq) { if (!snd.empty()) { - _vm->_snd->stopSound(0); - _vm->_snd->playSample(snd, repCount, freq); + _vm->_sound->blasterStop(0); + _vm->_sound->blasterPlay(&snd, repCount, freq); } } @@ -1216,7 +1217,7 @@ void Goblin::zeroObjects(void) { _objects[i] = 0; for (int i = 0; i < 16; i++) - _vm->_snd->freeSample(_soundData[i]); + _vm->_sound->sampleFree(&_soundData[i]); } void Goblin::freeAllObjects(void) { @@ -1717,12 +1718,12 @@ void Goblin::playSounds(Mult::Mult_Object *obj) { if (!speaker) { sndSlot = obj->goblinStates[animData->state][i].sndItem; - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); if (sndSlot < _soundSlotsCount) - _vm->_snd->playSample(_vm->_game->_soundSamples[_soundSlots[sndSlot] & 0x7FFF], + _vm->_sound->blasterPlay(_vm->_sound->sampleGetBySlot(_soundSlots[sndSlot] & 0x7FFF), repCount, frequency); } else - _vm->_snd->speakerOn(frequency, repCount * 10); + _vm->_sound->speakerOn(frequency, repCount * 10); } } diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index f7ac4aa549..3fd8a9f93b 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -27,8 +27,8 @@ #define GOB_GOBLIN_H #include "gob/util.h" -#include "gob/sound.h" #include "gob/mult.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/goblin_v1.cpp b/engines/gob/goblin_v1.cpp index f7bdbf10a5..6ac086767b 100644 --- a/engines/gob/goblin_v1.cpp +++ b/engines/gob/goblin_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -32,7 +31,7 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/scenery.h" -#include "gob/sound.h" +#include "gob/sound/sound.h" namespace Gob { @@ -48,7 +47,7 @@ void Goblin_v1::freeObjects(void) { int16 col; for (int i = 0; i < 16; i++) - _vm->_snd->freeSample(_soundData[i]); + _vm->_sound->sampleFree(&_soundData[i]); for (int i = 0; i < 4; i++) { if (_goblins[i] == 0) @@ -488,19 +487,19 @@ void Goblin_v1::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, if ((gobDesc->state >= 0) && (gobDesc->state < 10) && (gobDesc->stateMach == gobDesc->realStateMach) && ((gobDesc->curFrame == 3) || (gobDesc->curFrame == 6))) { - _vm->_snd->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5); + _vm->_sound->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5); } if ((_currentGoblin == 0) && (gobDesc->stateMach == gobDesc->realStateMach) && ((gobDesc->state == 10) || (gobDesc->state == 11)) && (gobDesc->curFrame == 9)) { - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); if (_itemIndInPocket != -1) - _vm->_snd->playSample(_soundData[14], 1, 9000); + _vm->_sound->blasterPlay(&_soundData[14], 1, 9000); else - _vm->_snd->playSample(_soundData[14], 1, 5000); + _vm->_sound->blasterPlay(&_soundData[14], 1, 5000); } if (_boreCounter++ == 120) { diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp index c9e155ad08..9144e35070 100644 --- a/engines/gob/goblin_v2.cpp +++ b/engines/gob/goblin_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -34,6 +33,7 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/scenery.h" +#include "gob/inter.h" namespace Gob { diff --git a/engines/gob/goblin_v4.cpp b/engines/gob/goblin_v4.cpp index 167946e30d..1df5aab606 100644 --- a/engines/gob/goblin_v4.cpp +++ b/engines/gob/goblin_v4.cpp @@ -29,6 +29,7 @@ #include "gob/mult.h" #include "gob/map.h" #include "gob/scenery.h" +#include "gob/inter.h" namespace Gob { diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index 4d184c53d3..c2f8b48626 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -31,13 +30,13 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/palanim.h" -#include "gob/sound.h" +#include "gob/inter.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -51,8 +50,8 @@ void Init::cleanup(void) { _vm->_video->freeDriver(); _vm->_global->_primarySurfDesc = 0; - _vm->_snd->speakerOff(); - _vm->_snd->stopSound(0); + _vm->_sound->speakerOff(); + _vm->_sound->blasterStop(0); _vm->_dataIO->closeDataFile(); } @@ -64,7 +63,6 @@ void Init::initGame(const char *totName) { char *infPtr; char *infEnd; char buffer[128]; - int32 varsCount; initVideo(); @@ -92,8 +90,6 @@ void Init::initGame(const char *totName) { _vm->_game->_totTextData = 0; _vm->_game->_totFileData = 0; _vm->_game->_totResourceTable = 0; - _vm->_global->_inter_variables = 0; - _vm->_global->_inter_variablesSizes = 0; _palDesc = new Video::PalDesc; _vm->validateVideoMode(_vm->_global->_videoMode); @@ -159,18 +155,14 @@ void Init::initGame(const char *totName) { DataStream *stream = _vm->_dataIO->openAsStream(handle, true); stream->seek(0x2C); - varsCount = stream->readUint16LE(); + _vm->_inter->allocateVars(stream->readUint16LE()); delete stream; - _vm->_global->_inter_variables = new byte[varsCount * 4]; - _vm->_global->_inter_variablesSizes = new byte[varsCount * 4]; - _vm->_global->clearVars(varsCount); - strcpy(_vm->_game->_curTotFile, buffer); - _vm->_cdrom->testCD(1, "GOB"); - _vm->_cdrom->readLIC("gob.lic"); + _vm->_sound->cdTest(1, "GOB"); + _vm->_sound->cdLoadLIC("gob.lic"); // Search for a Coktel logo animation or image to display imdHandle = _vm->_dataIO->openData("coktel.imd"); @@ -213,11 +205,9 @@ void Init::initGame(const char *totName) { _vm->_game->start(); - _vm->_cdrom->stopPlaying(); - _vm->_cdrom->freeLICbuffer(); + _vm->_sound->cdStop(); + _vm->_sound->cdUnloadLIC(); - delete[] _vm->_global->_inter_variables; - delete[] _vm->_global->_inter_variablesSizes; delete[] _vm->_game->_totFileData; if (_vm->_game->_totTextData) { if (_vm->_game->_totTextData->items) diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp index 8065c4dc8c..90456f927c 100644 --- a/engines/gob/init_v1.cpp +++ b/engines/gob/init_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp index bb29f4e8fd..b468c15c25 100644 --- a/engines/gob/init_v2.cpp +++ b/engines/gob/init_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -50,8 +49,8 @@ void Init_v2::initVideo() { _vm->_global->_inVM = 0; _vm->_global->_colorCount = 16; - if (((_vm->_platform == Common::kPlatformPC) || - (_vm->_platform == Common::kPlatformMacintosh)) && + if (((_vm->getPlatform() == Common::kPlatformPC) || + (_vm->getPlatform() == Common::kPlatformMacintosh)) && ((_vm->_global->_videoMode == 0x13) || (_vm->_global->_videoMode == 0x14))) _vm->_global->_colorCount = 256; diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index de3ac4b1f5..9c39653a1d 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -23,6 +23,7 @@ * */ +#include <time.h> // FIXME: for Inter::renewTimeInVars() #include "common/endian.h" @@ -34,9 +35,7 @@ #include "gob/game.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" - -#include <time.h> // FIXME: for Inter::renewTimeInVars() +#include "gob/sound/sound.h" namespace Gob { @@ -61,6 +60,12 @@ Inter::Inter(GobEngine *vm) : _vm(vm) { _pastePos = 0; _noBusyWait = false; + + _variables = 0; +} + +Inter::~Inter() { + delocateVars(); } void Inter::initControlVars(char full) { @@ -154,7 +159,7 @@ void Inter::storeKey(int16 key) { WRITE_VAR(12, _vm->_util->getTimeKey() - _vm->_game->_startTimeKey); storeMouse(); - WRITE_VAR(1, _vm->_snd->_playingSound); + WRITE_VAR(1, _vm->_sound->blasterPlayingSound()); if (key == 0x4800) key = 0x0B; @@ -280,4 +285,18 @@ void Inter::callSub(int16 retFlag) { _terminate = 1; } +void Inter::allocateVars(uint32 count) { + if ((_vm->getPlatform() == Common::kPlatformAmiga) || + (_vm->getPlatform() == Common::kPlatformMacintosh) || + (_vm->getPlatform() == Common::kPlatformAtariST)) + _variables = new VariablesBE(count * 4); + else + _variables = new VariablesLE(count * 4); +} + +void Inter::delocateVars() { + delete _variables; + _variables = 0; +} + } // End of namespace Gob diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 582e57a2d4..60b3974d6d 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -27,6 +27,7 @@ #define GOB_INTER_H #include "gob/goblin.h" +#include "gob/variables.h" namespace Gob { @@ -48,6 +49,8 @@ public: uint32 _soundEndTimeKey; int16 _soundStopVal; + Variables *_variables; + void initControlVars(char full); int16 load16(); char evalExpr(int16 *pRes); @@ -59,11 +62,14 @@ public: void funcBlock(int16 retFlag); void callSub(int16 retFlag); + void allocateVars(uint32 count); + void delocateVars(); + virtual int16 loadSound(int16 slot) = 0; virtual void animPalette() = 0; Inter(GobEngine *vm); - virtual ~Inter() {} + virtual ~Inter(); protected: struct OpFuncParams { @@ -83,7 +89,7 @@ protected: int16 _animPalHighIndex[8]; int16 _animPalDir[8]; - char _pasteBuf[300]; + byte _pasteBuf[300]; byte _pasteSizeBuf[300]; int16 _pastePos; @@ -519,6 +525,7 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j); virtual const char *getOpcodeGoblinDesc(int i); + void o4_initScreen(); void o4_playVmdOrMusic(); }; diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 702950d539..d493fb00d3 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -34,9 +33,9 @@ #include "gob/draw.h" #include "gob/game.h" #include "gob/palanim.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -768,9 +767,9 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { return; for (i = 0; i < 4; i++) - _vm->_snd->loadSample(samples[i], sndFiles[i]); - _vm->_snd->playComposition(comp, 0, samples, 4); - _vm->_snd->waitEndPlay(true, false); + _vm->_sound->sampleLoad(&samples[i], sndFiles[i]); + _vm->_sound->blasterPlayComposition(comp, 0, samples, 4); + _vm->_sound->blasterWaitEndPlay(true, false); _vm->_palAnim->fade(0, 0, 0); _vm->_video->clearSurf(_vm->_draw->_frontSurface); } @@ -787,12 +786,12 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { static const char *palFiles[] = {"2ou2.clt", "2ou3.clt", "2ou4.clt", "2ou5.clt"}; for (int i = 0; i < 2; i++) - _vm->_snd->loadSample(samples[i], sndFiles[i]); + _vm->_sound->sampleLoad(&samples[i], sndFiles[i]); for (int i = 0; i < 4; i++) palettes[i] = _vm->_dataIO->getData(palFiles[i]); palBak = _vm->_global->_pPaletteDesc->vgaPal; - _vm->_snd->playComposition(comp, 0, samples, 2); + _vm->_sound->blasterPlayComposition(comp, 0, samples, 2); for (int i = 0; i < 20; i++) { for (int j = 0; j < 4; j++) { _vm->_global->_pPaletteDesc->vgaPal = (Video::Color *) palettes[j]; @@ -801,7 +800,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { } if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || _vm->_quitRequested) { - _vm->_snd->stopSound(10); + _vm->_sound->blasterStop(10); _vm->_palAnim->fade(0, -2, 0); _vm->_video->clearSurf(_vm->_draw->_frontSurface); memset((char *) _vm->_draw->_vgaPalette, 0, 768); @@ -811,7 +810,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { break; } } - _vm->_snd->waitEndPlay(false, false); + _vm->_sound->blasterWaitEndPlay(false, false); _vm->_global->_pPaletteDesc->vgaPal = palBak; for (int i = 0; i < 4; i++) diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 9707a628b4..e2b8d65112 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/file.h" @@ -32,8 +31,6 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/music.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/goblin.h" @@ -43,8 +40,8 @@ #include "gob/palanim.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" +#include "gob/sound/sound.h" namespace Gob { @@ -932,16 +929,16 @@ void Inter_v1::o1_initMult() { _vm->_mult->_objCount * sizeof(Mult::Mult_Object)); for (int i = 0; i < _vm->_mult->_objCount; i++) { - _vm->_mult->_objects[i].pPosX = - (int32 *)(_vm->_global->_inter_variables + - i * 4 + (posXVar / 4) * 4); - _vm->_mult->_objects[i].pPosY = - (int32 *)(_vm->_global->_inter_variables + - i * 4 + (posYVar / 4) * 4); + uint32 offPosX = i * 4 + (posXVar / 4) * 4; + uint32 offPosY = i * 4 + (posYVar / 4) * 4; + uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize; + + _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX); + _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY); _vm->_mult->_objects[i].pAnimData = - (Mult::Mult_AnimData *) (_vm->_global->_inter_variables + - animDataVar + i * 4 * _vm->_global->_inter_animDataSize); + (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim, + _vm->_global->_inter_animDataSize); _vm->_mult->_objects[i].pAnimData->isStatic = 1; _vm->_mult->_objects[i].tick = 0; @@ -1071,12 +1068,8 @@ void Inter_v1::o1_loadCurLayer() { void Inter_v1::o1_playCDTrack() { evalExpr(0); - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->playTrack(_vm->_global->_inter_resStr); - } else - // Used in gob1 CD - _vm->_cdrom->startTrack(_vm->_global->_inter_resStr); + _vm->_sound->adlibPlayBgMusic(); // Mac version + _vm->_sound->cdPlay(_vm->_global->_inter_resStr); // PC CD version } void Inter_v1::o1_getCDTrackPos() { @@ -1088,19 +1081,15 @@ void Inter_v1::o1_getCDTrackPos() { _vm->_util->longDelay(1); - int pos = _vm->_cdrom->getTrackPos(); + int pos = _vm->_sound->cdGetTrackPos(); if (pos == -1) pos = 32767; WRITE_VAR(5, pos); } void Inter_v1::o1_stopCD() { - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); - } else - // Used in gob1 CD - _vm->_cdrom->stopPlaying(); + _vm->_sound->adlibStop(); // Mac version + _vm->_sound->cdStop(); // PC CD version } void Inter_v1::o1_loadFontToSprite() { @@ -1685,7 +1674,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { break; default: - _vm->_snd->speakerOnUpdate(cmd); + _vm->_sound->speakerOnUpdate(cmd); if (cmd < 20) { _vm->_util->delay(cmd); _noBusyWait = true; @@ -1759,12 +1748,12 @@ bool Inter_v1::o1_renewTimeInVars(OpFuncParams ¶ms) { } bool Inter_v1::o1_speakerOn(OpFuncParams ¶ms) { - _vm->_snd->speakerOn(_vm->_parse->parseValExpr(), -1); + _vm->_sound->speakerOn(_vm->_parse->parseValExpr(), -1); return false; } bool Inter_v1::o1_speakerOff(OpFuncParams ¶ms) { - _vm->_snd->speakerOff(); + _vm->_sound->speakerOff(); return false; } @@ -1978,10 +1967,10 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { repCount = _vm->_parse->parseValExpr(); frequency = _vm->_parse->parseValExpr(); - SoundDesc &sample = _vm->_game->_soundSamples[index]; + SoundDesc *sample = _vm->_sound->sampleGetBySlot(index); _soundEndTimeKey = 0; - if (sample.empty()) + if (!sample || sample->empty()) return false; if (repCount < 0) { @@ -1991,31 +1980,28 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { repCount = -repCount; _soundEndTimeKey = _vm->_util->getTimeKey(); - freq2 = frequency ? frequency : sample._frequency; + freq2 = frequency ? frequency : sample->_frequency; endRep = MAX(repCount - 1, 1); - _soundStopVal = sample.calcFadeOutLength(freq2); - _soundEndTimeKey += sample.calcLength(endRep, freq2, true); + _soundStopVal = sample->calcFadeOutLength(freq2); + _soundEndTimeKey += sample->calcLength(endRep, freq2, true); } - if (sample.getType() == SOUND_ADL) { - if (_vm->_adlib) { - _vm->_adlib->load(sample.getData(), sample.size(), index); - _vm->_adlib->setRepeating(repCount - 1); - _vm->_adlib->startPlay(); - } + if (sample->getType() == SOUND_ADL) { + _vm->_sound->adlibLoad(sample->getData(), sample->size(), index); + _vm->_sound->adlibSetRepeating(repCount - 1); + _vm->_sound->adlibPlay(); } else { - _vm->_snd->stopSound(0); - _vm->_snd->playSample(sample, repCount - 1, frequency); + _vm->_sound->blasterStop(0); + _vm->_sound->blasterPlay(sample, repCount - 1, frequency); } return false; } bool Inter_v1::o1_stopSound(OpFuncParams ¶ms) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); - _vm->_snd->stopSound(_vm->_parse->parseValExpr()); + _vm->_sound->adlibStop(); + _vm->_sound->blasterStop(_vm->_parse->parseValExpr()); _soundEndTimeKey = 0; return false; @@ -2032,7 +2018,7 @@ bool Inter_v1::o1_freeSoundSlot(OpFuncParams ¶ms) { } bool Inter_v1::o1_waitEndPlay(OpFuncParams ¶ms) { - _vm->_snd->waitEndPlay(); + _vm->_sound->blasterWaitEndPlay(); return false; } @@ -2046,7 +2032,7 @@ bool Inter_v1::o1_playComposition(OpFuncParams ¶ms) { for (int i = 0; i < 50; i++) composition[i] = (int16) VAR_OFFSET(dataVar + i * 4); - _vm->_snd->playComposition(composition, freqVal); + _vm->_sound->blasterPlayComposition(composition, freqVal); return false; } @@ -2083,8 +2069,7 @@ bool Inter_v1::o1_prepareStr(OpFuncParams ¶ms) { int16 strVar; strVar = _vm->_parse->parseVarIndex(); - _vm->_util->prepareStr(GET_VARO_STR(strVar)); - _vm->_global->writeVarSizeStr(strVar, strlen(GET_VARO_STR(strVar))); + _vm->_util->prepareStr(GET_VARO_FSTR(strVar)); return false; } @@ -2095,8 +2080,9 @@ bool Inter_v1::o1_insertStr(OpFuncParams ¶ms) { strVar = _vm->_parse->parseVarIndex(); evalExpr(0); pos = _vm->_parse->parseValExpr(); - _vm->_util->insertStr(_vm->_global->_inter_resStr, GET_VARO_STR(strVar), pos); - _vm->_global->writeVarSizeStr(strVar, strlen(GET_VARO_STR(strVar))); + + char *str = GET_VARO_FSTR(strVar); + _vm->_util->insertStr(_vm->_global->_inter_resStr, str, pos); return false; } @@ -2236,7 +2222,7 @@ bool Inter_v1::o1_readData(OpFuncParams ¶ms) { if (((dataVar >> 2) == 59) && (size == 4)) WRITE_VAR(59, stream->readUint32LE()); else - retSize = stream->read(_vm->_global->_inter_variables + dataVar, size); + retSize = stream->read((byte *) _variables->getAddressOff8(dataVar, size), size); if (retSize == size) WRITE_VAR(1, 0); @@ -2803,11 +2789,9 @@ void Inter_v1::o1_animateObjects(OpGobParams ¶ms) { void Inter_v1::o1_drawObjects(OpGobParams ¶ms) { _vm->_goblin->drawObjects(); - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->playBgMusic(); - } else if (_vm->_cdrom->getTrackPos() == -1) - _vm->_cdrom->playBgMusic(); + _vm->_sound->adlibPlayBgMusic(); // Mac version + if (_vm->_sound->cdGetTrackPos() == -1) + _vm->_sound->cdPlayBgMusic(); // PC CD version } void Inter_v1::o1_loadMap(OpGobParams ¶ms) { @@ -2993,9 +2977,11 @@ int16 Inter_v1::loadSound(int16 slot) { dataSize = (uint32) ((int32) totSize); } - if (dataPtr) - _vm->_game->_soundSamples[slot].load(SOUND_SND, source, - dataPtr, dataSize); + if (dataPtr) { + SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); + if (sample) + sample->load(SOUND_SND, source, dataPtr, dataSize); + } return 0; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index be510df08a..d8c33fcce6 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "sound/mixer.h" #include "sound/mods/infogrames.h" @@ -33,8 +32,6 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/music.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/goblin.h" @@ -42,10 +39,10 @@ #include "gob/mult.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/saveload.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -899,26 +896,23 @@ void Inter_v2::o2_initMult() { if (_terminate) return; - _vm->_mult->_orderArray = new uint8[_vm->_mult->_objCount]; + _vm->_mult->_orderArray = new int8[_vm->_mult->_objCount]; memset(_vm->_mult->_orderArray, 0, _vm->_mult->_objCount * sizeof(int8)); _vm->_mult->_objects = new Mult::Mult_Object[_vm->_mult->_objCount]; memset(_vm->_mult->_objects, 0, _vm->_mult->_objCount * sizeof(Mult::Mult_Object)); for (int i = 0; i < _vm->_mult->_objCount; i++) { - _vm->_mult->_objects[i].pPosX = - (int32 *)(_vm->_global->_inter_variables + - i * 4 + (posXVar / 4) * 4); - _vm->_mult->_objects[i].pPosY = - (int32 *)(_vm->_global->_inter_variables + - i * 4 + (posYVar / 4) * 4); + uint32 offPosX = i * 4 + (posXVar / 4) * 4; + uint32 offPosY = i * 4 + (posYVar / 4) * 4; + uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize; + + _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX); + _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY); _vm->_mult->_objects[i].pAnimData = - (Mult::Mult_AnimData *) (_vm->_global->_inter_variables + - animDataVar + i * 4 * _vm->_global->_inter_animDataSize); - memset(_vm->_global->_inter_variablesSizes + - i * 4 * _vm->_global->_inter_animDataSize, 0, - _vm->_global->_inter_animDataSize); + (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim, + _vm->_global->_inter_animDataSize); _vm->_mult->_objects[i].pAnimData->isStatic = 1; _vm->_mult->_objects[i].tick = 0; @@ -1086,16 +1080,18 @@ void Inter_v2::o2_playCDTrack() { _vm->_draw->blitInvalidated(); evalExpr(0); - _vm->_cdrom->startTrack(_vm->_global->_inter_resStr); + _vm->_sound->cdPlay(_vm->_global->_inter_resStr); } void Inter_v2::o2_waitCDTrackEnd() { - while (_vm->_cdrom->getTrackPos() >= 0) + debugC(1, kDebugSound, "CDROM: Waiting for playback to end"); + + while (_vm->_sound->cdGetTrackPos() >= 0) _vm->_util->longDelay(1); } void Inter_v2::o2_stopCD() { - _vm->_cdrom->stopPlaying(); + _vm->_sound->cdStop(); } void Inter_v2::o2_readLIC() { @@ -1105,11 +1101,11 @@ void Inter_v2::o2_readLIC() { strncpy0(path, _vm->_global->_inter_resStr, 35); strcat(path, ".LIC"); - _vm->_cdrom->readLIC(path); + _vm->_sound->cdLoadLIC(path); } void Inter_v2::o2_freeLIC() { - _vm->_cdrom->freeLICbuffer(); + _vm->_sound->cdUnloadLIC(); } void Inter_v2::o2_getCDTrackPos() { @@ -1121,8 +1117,8 @@ void Inter_v2::o2_getCDTrackPos() { varPos = _vm->_parse->parseVarIndex(); varName = _vm->_parse->parseVarIndex(); - WRITE_VAR_OFFSET(varPos, _vm->_cdrom->getTrackPos(GET_VARO_STR(varName))); - WRITE_VARO_STR(varName, _vm->_cdrom->getCurTrack()); + WRITE_VAR_OFFSET(varPos, _vm->_sound->cdGetTrackPos(GET_VARO_STR(varName))); + WRITE_VARO_STR(varName, _vm->_sound->cdGetCurrentTrack()); } void Inter_v2::o2_loadFontToSprite() { @@ -1187,10 +1183,7 @@ void Inter_v2::o2_copyVars() { varOff = _vm->_parse->parseVarIndex(); _vm->_global->_inter_execPtr++; - memcpy(_pasteBuf + _pastePos, _vm->_global->_inter_variables + varOff, - _vm->_global->_inter_animDataSize * 4); - memcpy(_pasteSizeBuf + _pastePos, - _vm->_global->_inter_variablesSizes + varOff, + _variables->copyTo(varOff, _pasteBuf + _pastePos, _pasteSizeBuf + _pastePos, _vm->_global->_inter_animDataSize * 4); _pastePos += _vm->_global->_inter_animDataSize * 4; @@ -1200,6 +1193,7 @@ void Inter_v2::o2_copyVars() { } else { if (evalExpr(&varOff) == 20) _vm->_global->_inter_resVal = 0; + memcpy(_pasteBuf + _pastePos, &_vm->_global->_inter_resVal, 4); memcpy(_pasteSizeBuf + _pastePos, &_vm->_global->_inter_resVal, 4); _pastePos += 4; @@ -1223,8 +1217,7 @@ void Inter_v2::o2_pasteVars() { assert(sizeV == sizeS); _pastePos -= sizeV; - memcpy(_vm->_global->_inter_variables + varOff, _pasteBuf + _pastePos, sizeV); - memcpy(_vm->_global->_inter_variablesSizes + varOff, _pasteSizeBuf + _pastePos, sizeS); + _variables->copyFrom(varOff, _pasteBuf + _pastePos, _pasteSizeBuf + _pastePos, sizeV); } } @@ -1434,46 +1427,17 @@ void Inter_v2::o2_initScreen() { if (height > 0) _vm->_video->_surfHeight = height; - if (videoMode == 0x18) { - - if (_vm->_video->_surfWidth < _vm->_width) - _vm->_video->_screenDeltaX = (_vm->_width - _vm->_video->_surfWidth) / 2; - else - _vm->_video->_screenDeltaX = 0; - - _vm->_global->_mouseMinX = _vm->_video->_screenDeltaX; - _vm->_global->_mouseMaxX = _vm->_video->_screenDeltaX + _vm->_video->_surfWidth - 1; - - - int16 screenHeight = _vm->_video->_surfHeight; - - _vm->_video->_surfHeight += offY; + _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY); + _vm->_video->_splitHeight2 = offY; + _vm->_video->_splitStart = _vm->_video->_surfHeight - offY; - _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, screenHeight - offY); - _vm->_video->_splitHeight2 = offY; - _vm->_video->_splitStart = screenHeight; + _vm->_video->_screenDeltaX = 0; + _vm->_video->_screenDeltaY = 0; - if ((_vm->_video->_surfHeight + offY) < _vm->_height) - _vm->_video->_screenDeltaY = (_vm->_height - (screenHeight + offY)) / 2; - else - _vm->_video->_screenDeltaY = 0; - - _vm->_global->_mouseMaxY = (screenHeight + _vm->_video->_screenDeltaY) - offY - 1; - _vm->_global->_mouseMinY = _vm->_video->_screenDeltaY; - - } else { - _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY); - _vm->_video->_splitHeight2 = offY; - _vm->_video->_splitStart = _vm->_video->_surfHeight - offY; - - _vm->_video->_screenDeltaX = 0; - _vm->_video->_screenDeltaY = 0; - - _vm->_global->_mouseMinX = 0; - _vm->_global->_mouseMinY = 0; - _vm->_global->_mouseMaxX = _vm->_width; - _vm->_global->_mouseMaxY = _vm->_height - _vm->_video->_splitHeight2 - 1; - } + _vm->_global->_mouseMinX = 0; + _vm->_global->_mouseMinY = 0; + _vm->_global->_mouseMaxX = _vm->_width; + _vm->_global->_mouseMaxY = _vm->_height - _vm->_video->_splitHeight2 - 1; _vm->_draw->closeScreen(); _vm->_util->clearPalette(); @@ -1532,18 +1496,27 @@ void Inter_v2::o2_scroll() { } void Inter_v2::o2_setScrollOffset() { - int16 offset; + int16 offsetX, offsetY; - offset = _vm->_parse->parseValExpr(); + offsetX = _vm->_parse->parseValExpr(); + offsetY = _vm->_parse->parseValExpr(); - if (offset == -1) { - _vm->_parse->parseValExpr(); + if (offsetX == -1) { WRITE_VAR(2, _vm->_draw->_scrollOffsetX); WRITE_VAR(3, _vm->_draw->_scrollOffsetY); } else { - _vm->_draw->_scrollOffsetX = offset; - _vm->_draw->_scrollOffsetY = _vm->_parse->parseValExpr(); + int16 screenW = _vm->_video->_surfWidth; + int16 screenH = _vm->_video->_surfHeight; + + if (screenW > _vm->_width) + screenW -= _vm->_width; + if (screenH > _vm->_height) + screenH -= _vm->_height; + + _vm->_draw->_scrollOffsetX = CLIP<int16>(offsetX, 0, screenW); + _vm->_draw->_scrollOffsetY = CLIP<int16>(offsetY, 0, screenH); } + _vm->_util->setScrollOffset(); _noBusyWait = true; } @@ -1574,8 +1547,12 @@ void Inter_v2::o2_playImd() { palEnd = _vm->_parse->parseValExpr(); palCmd = 1 << (flags & 0x3F); + debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " + "paletteCmd %d (%d - %d), flags %X", _vm->_global->_inter_resStr, x, y, + startFrame, lastFrame, palCmd, palStart, palEnd, flags); + if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) { - WRITE_VAR(11, -1); + WRITE_VAR(11, (uint32) -1); return; } @@ -1607,6 +1584,12 @@ void Inter_v2::o2_getImdInfo() { varWidth = _vm->_parse->parseVarIndex(); varHeight = _vm->_parse->parseVarIndex(); + // WORKAROUND: The nut rolling animation in the administration center + // in Woodruff is called "noixroul", but the scripts think it's "noixroule". + if ((_vm->getGameType() == kGameTypeWoodruff) && + (!scumm_stricmp(_vm->_global->_inter_resStr, "noixroule"))) + strcpy(_vm->_global->_inter_resStr, "noixroul"); + _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY, varFrames, varWidth, varHeight); } @@ -1883,10 +1866,9 @@ bool Inter_v2::o2_stopSound(OpFuncParams ¶ms) { expr = _vm->_parse->parseValExpr(); if (expr < 0) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); + _vm->_sound->adlibStop(); } else - _vm->_snd->stopSound(expr); + _vm->_sound->blasterStop(expr); _soundEndTimeKey = 0; return false; @@ -1915,7 +1897,7 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { int16 handle; int16 varOff; int32 size; - SaveType type; + SaveLoad::SaveMode mode; evalExpr(0); varOff = _vm->_parse->parseVarIndex(); @@ -1923,8 +1905,8 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { size = -1; handle = 1; - type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr); - if (type == kSaveNone) { + mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + if (mode == SaveLoad::kSaveModeNone) { handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); if (handle >= 0) { @@ -1932,8 +1914,8 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr); } else warning("File \"%s\" not found", _vm->_global->_inter_resStr); - } else - size = _vm->_saveLoad->getSize(type); + } else if (mode == SaveLoad::kSaveModeSave) + size = _vm->_saveLoad->getSize(_vm->_global->_inter_resStr); if (size == -1) handle = -1; @@ -1954,7 +1936,7 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { int16 dataVar; int16 handle; byte *buf; - SaveType type; + SaveLoad::SaveMode mode; evalExpr(0); dataVar = _vm->_parse->parseVarIndex(); @@ -1966,13 +1948,14 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)", _vm->_global->_inter_resStr, dataVar, size, offset); - type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr); - if (type != kSaveNone) { + mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + if (mode == SaveLoad::kSaveModeSave) { WRITE_VAR(1, 1); - if (_vm->_saveLoad->load(type, dataVar, size, offset)) + if (_vm->_saveLoad->load(_vm->_global->_inter_resStr, dataVar, size, offset)) WRITE_VAR(1, 0); return false; - } + } else if (mode == SaveLoad::kSaveModeIgnore) + return false; if (size < 0) { warning("Attempted to read a raw sprite from file \"%s\"", @@ -1983,8 +1966,7 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; } - buf = _vm->_global->_inter_variables + dataVar; - memset(_vm->_global->_inter_variablesSizes + dataVar, 0, size); + buf = _variables->getAddressOff8(dataVar, size); if (_vm->_global->_inter_resStr[0] == 0) { WRITE_VAR(1, size); @@ -2009,7 +1991,7 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { WRITE_VAR(59, stream->readUint32LE()); // The scripts in some versions divide through 256^3 then, // effectively doing a LE->BE conversion - if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256)) + if ((_vm->getPlatform() != Common::kPlatformPC) && (VAR(59) < 256)) WRITE_VAR(59, SWAP_BYTES_32(VAR(59))); } else retSize = stream->read(buf, size); @@ -2025,7 +2007,7 @@ bool Inter_v2::o2_writeData(OpFuncParams ¶ms) { int32 offset; int32 size; int16 dataVar; - SaveType type; + SaveLoad::SaveMode mode; evalExpr(0); dataVar = _vm->_parse->parseVarIndex(); @@ -2038,11 +2020,11 @@ bool Inter_v2::o2_writeData(OpFuncParams ¶ms) { WRITE_VAR(1, 1); - type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr); - if (type != kSaveNone) { - if (_vm->_saveLoad->save(type, dataVar, size, offset)) + mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + if (mode == SaveLoad::kSaveModeSave) { + if (_vm->_saveLoad->save(_vm->_global->_inter_resStr, dataVar, size, offset)) WRITE_VAR(1, 0); - } else + } else if (mode == SaveLoad::kSaveModeNone) warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr); return false; @@ -2054,29 +2036,10 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams ¶ms) { varName = load16(); - if (_vm->_noMusic) - return; - strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".INS"); - debugC(1, kDebugMusic, "Loading Infogrames instrument file \"%s\"", - fileName); - - if (_vm->_game->_infogrames) { - _vm->_mixer->stopHandle(_vm->_game->_infHandle); - delete _vm->_game->_infogrames; - _vm->_game->_infogrames = 0; - } - - if (_vm->_game->_infIns) - delete _vm->_game->_infIns; - _vm->_game->_infIns = new Audio::Infogrames::Instruments; - if (!_vm->_game->_infIns->load(fileName)) { - warning("Couldn't load instruments file"); - delete _vm->_game->_infIns; - _vm->_game->_infIns = 0; - } + _vm->_sound->infogramesLoadInstruments(fileName); } void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { @@ -2085,58 +2048,23 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { varName = load16(); - if (_vm->_noMusic) - return; - strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".DUM"); - debugC(1, kDebugMusic, "Playing Infogrames music file \"%s\"", fileName); - if (!_vm->_game->_infIns) { - _vm->_game->_infIns = new Audio::Infogrames::Instruments; - - if (!_vm->_game->_infIns->load("i1.ins")) { - warning("Couldn't load instruments file"); - delete _vm->_game->_infIns; - _vm->_game->_infIns = 0; - } - } - - if (_vm->_game->_infIns) { - _vm->_mixer->stopHandle(_vm->_game->_infHandle); - delete _vm->_game->_infogrames; - _vm->_game->_infogrames = - new Audio::Infogrames(*_vm->_game->_infIns, true, - _vm->_mixer->getOutputRate(), - _vm->_mixer->getOutputRate() / 75); - - if (!_vm->_game->_infogrames->load(fileName)) { - warning("Couldn't load infogrames music"); - delete _vm->_game->_infogrames; - _vm->_game->_infogrames = 0; - } else - _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_vm->_game->_infHandle, _vm->_game->_infogrames, - -1, 255, 0, false); - } + _vm->_sound->infogramesLoadSong(fileName); + _vm->_sound->infogramesPlay(); } void Inter_v2::o2_startInfogrames(OpGobParams ¶ms) { load16(); - if (_vm->_game->_infogrames && - !_vm->_mixer->isSoundHandleActive(_vm->_game->_infHandle)) { - _vm->_game->_infogrames->restart(); - _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_vm->_game->_infHandle, _vm->_game->_infogrames, - -1, 255, 0, false); - } + _vm->_sound->infogramesPlay(); } void Inter_v2::o2_stopInfogrames(OpGobParams ¶ms) { load16(); - _vm->_mixer->stopHandle(_vm->_game->_infHandle); + _vm->_sound->infogramesStop(); } void Inter_v2::o2_handleGoblins(OpGobParams ¶ms) { @@ -2172,15 +2100,15 @@ int16 Inter_v2::loadSound(int16 search) { } else { id = load16(); - for (slot = 0; slot < 60; slot++) - if (_vm->_game->_soundSamples[slot].isId(id)) { + for (slot = 0; slot < Sound::kSoundsCount; slot++) + if (_vm->_sound->sampleGetBySlot(slot)->isId(id)) { slotIdMask = 0x8000; break; } - if (slot == 60) { - for (slot = 59; slot >= 0; slot--) { - if (_vm->_game->_soundSamples[slot].empty()) + if (slot == Sound::kSoundsCount) { + for (slot = (Sound::kSoundsCount - 1); slot >= 0; slot--) { + if (_vm->_sound->sampleGetBySlot(slot)->empty()) break; } @@ -2192,7 +2120,9 @@ int16 Inter_v2::loadSound(int16 search) { } } - _vm->_game->freeSoundSlot(slot); + SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); + + _vm->_sound->sampleFree(sample, true, slot); if (id == -1) { char sndfile[14]; @@ -2224,8 +2154,8 @@ int16 Inter_v2::loadSound(int16 search) { } if (dataPtr) { - _vm->_game->_soundSamples[slot].load(type, source, dataPtr, dataSize); - _vm->_game->_soundSamples[slot]._id = id; + sample->load(type, source, dataPtr, dataSize); + sample->_id = id; } return slot | slotIdMask; diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index b24e54ffbd..fb895dd5b2 100644 --- a/engines/gob/inter_v4.cpp +++ b/engines/gob/inter_v4.cpp @@ -29,9 +29,11 @@ #include "gob/gob.h" #include "gob/inter.h" #include "gob/global.h" +#include "gob/draw.h" #include "gob/game.h" #include "gob/parse.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -278,7 +280,7 @@ void Inter_v4::setupOpcodes() { {NULL, ""}, {NULL, ""}, /* 80 */ - OPCODE(o2_initScreen), + OPCODE(o4_initScreen), OPCODE(o2_scroll), OPCODE(o2_setScrollOffset), OPCODE(o4_playVmdOrMusic), @@ -503,7 +505,7 @@ void Inter_v4::setupOpcodes() { /* 30 */ OPCODE(o1_returnTo), OPCODE(o1_loadSpriteContent), - OPCODE(o3_copySprite), + OPCODE(o1_copySprite), OPCODE(o1_fillRect), /* 34 */ OPCODE(o1_drawLine), @@ -641,7 +643,7 @@ void Inter_v4::setupOpcodes() { void Inter_v4::executeDrawOpcode(byte i) { debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); + i, i, getOpcodeDrawDesc(i)); OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc; @@ -652,8 +654,10 @@ void Inter_v4::executeDrawOpcode(byte i) { } bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); + debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", + i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, + (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), + (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); if ((i > 4) || (j > 15)) { warning("unimplemented opcodeFunc: %d.%d", i, j); @@ -672,7 +676,7 @@ bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { void Inter_v4::executeGoblinOpcode(int i, OpGobParams ¶ms) { debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); + i, i, getOpcodeGoblinDesc(i)); OpcodeGoblinProcV4 op = NULL; @@ -683,6 +687,8 @@ void Inter_v4::executeGoblinOpcode(int i, OpGobParams ¶ms) { } if (op == NULL) { + warning("unimplemented opcodeGoblin: %d", i); + int16 val; _vm->_global->_inter_execPtr -= 2; @@ -710,6 +716,86 @@ const char *Inter_v4::getOpcodeGoblinDesc(int i) { return ""; } +void Inter_v4::o4_initScreen() { + int16 offY; + int16 videoMode; + int16 width, height; + + offY = load16(); + + videoMode = offY & 0xFF; + offY = (offY >> 8) & 0xFF; + + width = _vm->_parse->parseValExpr(); + height = _vm->_parse->parseValExpr(); + + _vm->_video->clearScreen(); + + _vm->_global->_fakeVideoMode = videoMode; + + // Some versions require this + if (videoMode == 0xD) + videoMode = _vm->_mode; + + if ((videoMode == _vm->_global->_videoMode) && (width == -1)) + return; + + if (width > 0) + _vm->_video->_surfWidth = width; + if (height > 0) + _vm->_video->_surfHeight = height; + + _vm->_video->_screenDeltaX = 0; + if (_vm->_video->_surfWidth < _vm->_width) + _vm->_video->_screenDeltaX = (_vm->_width - _vm->_video->_surfWidth) / 2; + + _vm->_global->_mouseMinX = _vm->_video->_screenDeltaX; + _vm->_global->_mouseMaxX = _vm->_video->_screenDeltaX + _vm->_video->_surfWidth - 1; + + _vm->_video->_splitStart = _vm->_video->_surfHeight - offY; + + _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight); + _vm->_video->_splitHeight2 = offY; + + if ((_vm->_video->_surfHeight + offY) < _vm->_height) + _vm->_video->_screenDeltaY = (_vm->_height - (_vm->_video->_surfHeight + offY)) / 2; + else + _vm->_video->_screenDeltaY = 0; + + _vm->_global->_mouseMaxY = (_vm->_video->_surfHeight + _vm->_video->_screenDeltaY) - offY - 1; + _vm->_global->_mouseMinY = _vm->_video->_screenDeltaY; + + _vm->_draw->closeScreen(); + _vm->_util->clearPalette(); + memset(_vm->_global->_redPalette, 0, 256); + memset(_vm->_global->_greenPalette, 0, 256); + memset(_vm->_global->_bluePalette, 0, 256); + + _vm->_video->_splitSurf = 0; + _vm->_draw->_spritesArray[24] = 0; + _vm->_draw->_spritesArray[25] = 0; + + _vm->_global->_videoMode = videoMode; + _vm->_video->initPrimary(videoMode); + WRITE_VAR(15, _vm->_global->_fakeVideoMode); + + _vm->_global->_setAllPalette = true; + + _vm->_util->setMousePos(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); + _vm->_util->clearPalette(); + + _vm->_draw->initScreen(); + + _vm->_util->setScrollOffset(); + + if (offY > 0) { + _vm->_draw->_spritesArray[24] = new SurfaceDesc(videoMode, _vm->_width, offY); + _vm->_draw->_spritesArray[25] = new SurfaceDesc(videoMode, _vm->_width, offY); + _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25]; + } +} + void Inter_v4::o4_playVmdOrMusic() { char fileName[128]; int16 x, y; @@ -725,6 +811,12 @@ void Inter_v4::o4_playVmdOrMusic() { evalExpr(0); strncpy0(fileName, _vm->_global->_inter_resStr, 127); + // WORKAROUND: The nut rolling animation in the administration center + // in Woodruff is called "noixroul", but the scripts think it's "noixroule". + if ((_vm->getGameType() == kGameTypeWoodruff) && + (!scumm_stricmp(fileName, "noixroule"))) + strcpy(fileName, "noixroul"); + x = _vm->_parse->parseValExpr(); y = _vm->_parse->parseValExpr(); startFrame = _vm->_parse->parseValExpr(); @@ -735,11 +827,14 @@ void Inter_v4::o4_playVmdOrMusic() { palEnd = _vm->_parse->parseValExpr(); palCmd = 1 << (flags & 0x3F); + debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " + "paletteCmd %d (%d - %d), flags %X", fileName, x, y, startFrame, lastFrame, + palCmd, palStart, palEnd, flags); + close = false; if (lastFrame == -1) { close = true; } else if (lastFrame == -3) { - warning("Woodruff Stub: Video/Music command -3: Play background video %s, %d, %d, %d, %d", fileName, startFrame, x, y, VAR_OFFSET(7872)); _vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1; @@ -763,16 +858,19 @@ void Inter_v4::o4_playVmdOrMusic() { warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName); return; } else if (lastFrame == -5) { - warning("Woodruff Stub: Video/Music command -5: Stop background music"); + _vm->_sound->bgStop(); return; } else if (lastFrame == -6) { - warning("Woodruff Stub: Video/Music command -6: Load background video %s", fileName); + return; + } else if (lastFrame == -7) { return; } else if (lastFrame == -8) { warning("Woodruff Stub: Video/Music command -8: Play background video %s", fileName); return; } else if (lastFrame == -9) { - warning("Woodruff Stub: Video/Music command -9: Play background music %s (%d-%d)", fileName, palEnd, palStart); + _vm->_sound->bgStop(); + _vm->_sound->bgSetPlayMode(BackgroundAtmosphere::kPlayModeRandom); + _vm->_sound->bgPlay(fileName, palStart); return; } else if (lastFrame < 0) { warning("Unknown Video/Music command: %d, %s", lastFrame, fileName); @@ -785,7 +883,7 @@ void Inter_v4::o4_playVmdOrMusic() { } if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) { - WRITE_VAR(11, -1); + WRITE_VAR(11, (uint32) -1); return; } diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp index cd8f9e3758..75867aaa6c 100644 --- a/engines/gob/map.cpp +++ b/engines/gob/map.cpp @@ -23,8 +23,6 @@ * */ - - #include "gob/gob.h" #include "gob/map.h" #include "gob/goblin.h" diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp index c4b68fad85..4ac99d2465 100644 --- a/engines/gob/map_v1.cpp +++ b/engines/gob/map_v1.cpp @@ -23,15 +23,14 @@ * */ - #include "common/stream.h" #include "gob/gob.h" #include "gob/map.h" #include "gob/dataio.h" #include "gob/goblin.h" -#include "gob/sound.h" #include "gob/mult.h" +#include "gob/sound/sound.h" namespace Gob { @@ -160,7 +159,7 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) { strcpy(sndNames[i], buf); } - _vm->_snd->loadSample(_vm->_goblin->_soundData[14], "diamant1.snd"); + _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], "diamant1.snd"); for (int i = 0; i < count; i++) { handle = _vm->_dataIO->openData(sndNames[i]); @@ -168,7 +167,7 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) { continue; _vm->_dataIO->closeData(handle); - _vm->_snd->loadSample(_vm->_goblin->_soundData[i], sndNames[i]); + _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], sndNames[i]); } } diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp index 2c383f5bb2..bd9f5b3efc 100644 --- a/engines/gob/map_v2.cpp +++ b/engines/gob/map_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/stream.h" #include "gob/gob.h" @@ -57,12 +56,12 @@ void Map_v2::loadMapObjects(const char *avjFile) { uint32 passPos; var = _vm->_parse->parseVarIndex(); - variables = _vm->_global->_inter_variables + var; + variables = _vm->_inter->_variables->getAddressOff8(var, 0); id = _vm->_inter->load16(); if (id == -1) { - _passMap = (int8 *)(_vm->_global->_inter_variables + var); + _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var, 0); return; } @@ -105,18 +104,17 @@ void Map_v2::loadMapObjects(const char *avjFile) { // In the original asm, this writes byte-wise into the variables-array tmpPos = mapData.pos(); mapData.seek(passPos); - if (variables != _vm->_global->_inter_variables) { - byte *sizes; + if ((variables != 0) && + (variables != _vm->_inter->_variables->getAddressOff8(0, 0))) { _passMap = (int8 *) variables; mapHeight = _screenHeight / _tilesHeight; mapWidth = _screenWidth / _tilesWidth; - sizes = _vm->_global->_inter_variablesSizes + - (((byte *) _passMap) - _vm->_global->_inter_variables); + for (int i = 0; i < mapHeight; i++) { for (int j = 0; j < mapWidth; j++) setPass(j, i, mapData.readSByte()); - memset(sizes + i * _passWidth, 0, mapWidth); + _vm->_inter->_variables->getAddressOff8(var + i * _passWidth, mapWidth); } } mapData.seek(tmpPos); diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp index 721f040341..3a74c4b6aa 100644 --- a/engines/gob/map_v4.cpp +++ b/engines/gob/map_v4.cpp @@ -54,7 +54,7 @@ void Map_v4::loadMapObjects(const char *avjFile) { uint32 passPos; var = _vm->_parse->parseVarIndex(); - variables = _vm->_global->_inter_variables + var; + variables = _vm->_inter->_variables->getAddressOff8(var, 0); id = _vm->_inter->load16(); @@ -62,7 +62,7 @@ void Map_v4::loadMapObjects(const char *avjFile) { warning("Woodruff Stub: loadMapObjects ID >= 65520"); return; } else if (id == -1) { - _passMap = (int8 *)(_vm->_global->_inter_variables + var); + _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var, 0); return; } @@ -113,25 +113,24 @@ void Map_v4::loadMapObjects(const char *avjFile) { } if (_widthByte == 4) - _mapWidth = (int16) READ_VARO_UINT16(68); + _mapWidth = VAR(17); _passWidth = _mapWidth; // In the original asm, this writes byte-wise into the variables-array tmpPos = mapData.pos(); mapData.seek(passPos); - if (variables != _vm->_global->_inter_variables) { - byte *sizes; + if ((variables != 0) && + (variables != _vm->_inter->_variables->getAddressOff8(0, 0))) { _passMap = (int8 *) variables; mapHeight = _screenHeight / _tilesHeight; mapWidth = _screenWidth / _tilesWidth; - sizes = _vm->_global->_inter_variablesSizes + - (((byte *) _passMap) - _vm->_global->_inter_variables); + for (int i = 0; i < mapHeight; i++) { for (int j = 0; j < mapWidth; j++) setPass(j, i, mapData.readSByte()); - memset(sizes + i * _passWidth, 0, mapWidth); + _vm->_inter->_variables->getAddressOff8(var + i * _passWidth, mapWidth); } } mapData.seek(tmpPos); diff --git a/engines/gob/module.mk b/engines/gob/module.mk index aa2a235327..45048a0899 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -1,7 +1,6 @@ MODULE := engines/gob MODULE_OBJS := \ - cdrom.o \ dataio.o \ detection.o \ draw.o \ @@ -38,7 +37,6 @@ MODULE_OBJS := \ mult.o \ mult_v1.o \ mult_v2.o \ - music.o \ palanim.o \ parse.o \ parse_v1.o \ @@ -46,14 +44,24 @@ MODULE_OBJS := \ saveload.o \ saveload_v2.o \ saveload_v3.o \ + saveload_v4.o \ scenery.o \ scenery_v1.o \ scenery_v2.o \ - sound.o \ util.o \ + variables.o \ video.o \ video_v1.o \ - video_v2.o + video_v2.o \ + sound/sound.o \ + sound/sounddesc.o \ + sound/pcspeaker.o \ + sound/adlib.o \ + sound/infogrames.o \ + sound/soundmixer.o \ + sound/soundblaster.o \ + sound/cdrom.o \ + sound/bgatmosphere.o # This module can be built as a plugin ifeq ($(ENABLE_GOB), DYNAMIC_PLUGIN) diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 70b6d33136..3d6a7942f9 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -34,9 +33,10 @@ #include "gob/game.h" #include "gob/palanim.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/inter.h" +#include "gob/sound/sound.h" namespace Gob { @@ -188,7 +188,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, if (_frame >= endFrame) stopNoClear = true; - if (_vm->_snd->_playingSound) + if (_vm->_sound->blasterPlayingSound()) stop = false; _vm->_util->processInput(); @@ -225,8 +225,8 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, _animDataAllocated = false; } - if (_vm->_snd->_playingSound) - _vm->_snd->stopSound(10); + if (_vm->_sound->blasterPlayingSound()) + _vm->_sound->blasterStop(10); WRITE_VAR(57, (uint32) -1); } else @@ -415,21 +415,24 @@ void Mult::doSoundAnim(bool &stop, int16 frame) { if (sndKey->cmd != -1) { if ((sndKey->cmd == 1) || (sndKey->cmd == 4)) { - SoundDesc &sample = _vm->_game->_soundSamples[sndKey->soundIndex]; + SoundDesc *sample = _vm->_sound->sampleGetBySlot(sndKey->soundIndex); - _vm->_snd->stopSound(0); - if (!sample.empty()) - _vm->_snd->playSample(sample, sndKey->repCount, + _vm->_sound->blasterStop(0); + if (sample && !sample->empty()) + _vm->_sound->blasterPlay(sample, sndKey->repCount, sndKey->freq, sndKey->fadeLength); } } else { - if (_vm->_snd->_playingSound) - _vm->_snd->stopSound(sndKey->fadeLength); + if (_vm->_sound->blasterPlayingSound()) + _vm->_sound->blasterStop(sndKey->fadeLength); } } } void Mult::clearObjectVideos() { + if (!_objects) + return; + for (int i = 0; i < _objCount; i++) if (_objects[i].videoSlot > 0) _vm->_vidPlayer->slotClose(_objects[i].videoSlot - 1); diff --git a/engines/gob/mult.h b/engines/gob/mult.h index c283191ec8..aaf2e2826c 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -40,7 +40,7 @@ public: uint8 layer; uint8 frame; int8 animType; - uint8 order; + int8 order; int8 isPaused; int8 isStatic; int8 maxTick; @@ -229,7 +229,7 @@ public: int16 *_renderData; Mult_Object **_renderObjs; - uint8 *_orderArray; + int8 *_orderArray; SurfaceDesc::Ptr _animSurf; int16 _animLeft; diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index 78071f1dd8..22683437e7 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 02211880ba..3a83ac1867 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" @@ -526,14 +525,14 @@ void Mult_v2::playMultInit() { delete[] _animArrayData; _objects = new Mult_Object[_objCount]; - _orderArray = new uint8[_objCount]; + _orderArray = new int8[_objCount]; _renderObjs = new Mult_Object*[_objCount]; _animArrayX = new int32[_objCount]; _animArrayY = new int32[_objCount]; _animArrayData = new Mult_AnimData[_objCount]; memset(_objects, 0, _objCount * sizeof(Mult_Object)); - memset(_orderArray, 0, _objCount * sizeof(uint8)); + memset(_orderArray, 0, _objCount * sizeof(int8)); memset(_renderObjs, 0, _objCount * sizeof(Mult_Object *)); memset(_animArrayX, 0, _objCount * sizeof(int32)); memset(_animArrayY, 0, _objCount * sizeof(int32)); @@ -686,6 +685,11 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) { return; animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer); + } else { + if (animObj.videoSlot > 0) { + _vm->_video->retrace(); + _vm->_vidPlayer->slotWaitEndFrame(animObj.videoSlot - 1, true); + } } if (animData.animType == 4) { @@ -693,7 +697,7 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) { animData.frame = 0; animData.isPaused = 1; if (animData.animation < 0) - warning("TODO: AnimType 4, animation: %d", animData.animation); + warning("Woodruff Stub: AnimType 4, animation: %d", animData.animation); return; } @@ -701,9 +705,8 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) { animData.animType = 11; if (animData.animType == 11) { - if (animData.isBusy != 0) { - warning("TODO: AnimType 11"); - } + if (animData.isBusy != 0) + warning("Woodruff Stub: AnimType 11"); return; } @@ -750,27 +753,39 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) { case 5: animData.isStatic = 1; animData.frame = 0; + if ((animData.animation < 0) && (animObj.videoSlot > 0)) { + _vm->_vidPlayer->slotClose(animObj.videoSlot - 1); + animObj.videoSlot = 0; + } + break; case 6: case 7: animData.frame--; animData.isPaused = 1; +/* if ((animData.animation < 0) && (animObj.videoSlot > 0)) { if (_vm->_vidPlayer->getFlags(animObj.videoSlot - 1) & 0x1000) { _vm->_vidPlayer->slotClose(animObj.videoSlot - 1); animObj.videoSlot = 0; } } +*/ + break; + + case 10: + warning("Woodruff Stub: AnimType 10"); break; } + animData.newCycle = 1; } void Mult_v2::animate() { - uint8 minOrder = 100; - uint8 maxOrder = 0; - uint8 *orderArray; + int8 minOrder = 100; + int8 maxOrder = 0; + int8 *orderArray; int orderArrayPos = 0; int8 animIndices[150]; int numAnims = 0; @@ -952,60 +967,58 @@ void Mult_v2::animate() { Mult_Object &animObj1 = *_renderObjs[orderArray[i]]; Mult_AnimData &animData1 = *(animObj1.pAnimData); - if (!animObj1.needRedraw && !animData1.isStatic) { - for (int j = 0; j < orderArrayPos; j++) { - Mult_Object &animObj2 = *_renderObjs[orderArray[j]]; + if (!animObj1.needRedraw) { - if (!animObj2.needRedraw) - continue; + if (!animData1.isStatic) { + for (int j = 0; j < orderArrayPos; j++) { + Mult_Object &animObj2 = *_renderObjs[orderArray[j]]; + + if (!animObj2.needRedraw) + continue; - if ((animObj1.newRight >= animObj2.newLeft) && - (animObj2.newRight >= animObj1.newLeft) && - (animObj1.newBottom >= animObj2.newTop) && - (animObj2.newBottom >= animObj1.newTop)) { + if ((animObj1.newRight >= animObj2.newLeft) && + (animObj2.newRight >= animObj1.newLeft) && + (animObj1.newBottom >= animObj2.newTop) && + (animObj2.newBottom >= animObj1.newTop)) { - _vm->_scenery->_toRedrawLeft = animObj2.newLeft; - _vm->_scenery->_toRedrawRight = animObj2.newRight; - _vm->_scenery->_toRedrawTop = animObj2.newTop; - _vm->_scenery->_toRedrawBottom = animObj2.newBottom; + _vm->_scenery->_toRedrawLeft = animObj2.newLeft; + _vm->_scenery->_toRedrawRight = animObj2.newRight; + _vm->_scenery->_toRedrawTop = animObj2.newTop; + _vm->_scenery->_toRedrawBottom = animObj2.newBottom; - _vm->_scenery->updateAnim(animData1.layer, animData1.frame, - animData1.animation, 12, *animObj1.pPosX, *animObj1.pPosY, 1); - _vm->_scenery->updateStatic(animData1.order + 1); + _vm->_scenery->updateAnim(animData1.layer, animData1.frame, + animData1.animation, 12, *animObj1.pPosX, *animObj1.pPosY, 1); + _vm->_scenery->updateStatic(animData1.order + 1); + } } } - } else if (!animData1.isStatic) { - _vm->_scenery->updateAnim(animData1.layer, animData1.frame, - animData1.animation, 10, *animObj1.pPosX, *animObj1.pPosY, 1); - - if (_vm->_scenery->_toRedrawLeft != -12345) { - if (_vm->_global->_pressedKeys[0x36]) { - _vm->_video->drawLine(_vm->_draw->_frontSurface, - _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawTop, - _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawTop, 15); - _vm->_video->drawLine(_vm->_draw->_frontSurface, - _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawBottom, - _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawBottom, 15); - _vm->_video->drawLine(_vm->_draw->_frontSurface, - _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawTop, - _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawBottom, 15); - _vm->_video->drawLine(_vm->_draw->_frontSurface, - _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawTop, - _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawBottom, 15); - } - animObj1.lastLeft = _vm->_scenery->_toRedrawLeft; - animObj1.lastRight = _vm->_scenery->_toRedrawRight; - animObj1.lastTop = _vm->_scenery->_toRedrawTop; - animObj1.lastBottom = _vm->_scenery->_toRedrawBottom; - } else - animObj1.lastLeft = -1; + } else { - _vm->_scenery->_toRedrawLeft = animObj1.newLeft; - _vm->_scenery->_toRedrawRight = animObj1.newRight; - _vm->_scenery->_toRedrawTop = animObj1.newTop; - _vm->_scenery->_toRedrawBottom = animObj1.newBottom; + + if (animData1.isStatic != 0) { + _vm->_scenery->_toRedrawLeft = animObj1.newLeft; + _vm->_scenery->_toRedrawRight = animObj1.newRight; + _vm->_scenery->_toRedrawTop = animObj1.newTop; + _vm->_scenery->_toRedrawBottom = animObj1.newBottom; + } else { + _vm->_scenery->updateAnim(animData1.layer, animData1.frame, + animData1.animation, 10, *animObj1.pPosX, *animObj1.pPosY, 1); + + if (_vm->_scenery->_toRedrawLeft != -12345) { + animObj1.lastLeft = _vm->_scenery->_toRedrawLeft; + animObj1.lastRight = _vm->_scenery->_toRedrawRight; + animObj1.lastTop = _vm->_scenery->_toRedrawTop; + animObj1.lastBottom = _vm->_scenery->_toRedrawBottom; + } else { + animObj1.lastLeft = -1; + } + + } + + _vm->_scenery->updateStatic(animData1.order + 1); + } - _vm->_scenery->updateStatic(animData1.order + 1); + } // Advance animations diff --git a/engines/gob/parse.cpp b/engines/gob/parse.cpp index af12626c83..ad1f53bb6f 100644 --- a/engines/gob/parse.cpp +++ b/engines/gob/parse.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -45,7 +44,7 @@ int32 Parse::encodePtr(byte *ptr, int type) { offset = ptr - _vm->_game->_totFileData; break; case kInterVar: - offset = ptr - _vm->_global->_inter_variables; + offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0, 0)); break; case kResStr: offset = ptr - ((byte *) _vm->_global->_inter_resStr); @@ -65,7 +64,7 @@ byte *Parse::decodePtr(int32 n) { ptr = _vm->_game->_totFileData; break; case kInterVar: - ptr = _vm->_global->_inter_variables; + ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0, 0); break; case kResStr: ptr = (byte *) _vm->_global->_inter_resStr; diff --git a/engines/gob/parse_v1.cpp b/engines/gob/parse_v1.cpp index 2b84ac5cee..3c5f90c068 100644 --- a/engines/gob/parse_v1.cpp +++ b/engines/gob/parse_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -376,7 +375,7 @@ int16 Parse_v1::parseExpr(byte stopToken, byte *arg_2) { case 25: *operPtr = 22; temp = _vm->_inter->load16() * 4; - *valPtr = encodePtr(_vm->_global->_inter_variables + temp, + *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp, 0), kInterVar); if (*_vm->_global->_inter_execPtr == 13) { _vm->_global->_inter_execPtr++; @@ -404,8 +403,8 @@ int16 Parse_v1::parseExpr(byte stopToken, byte *arg_2) { *valPtr = VAR(temp + offset); break; } - *valPtr = encodePtr(_vm->_global->_inter_variables + - temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, + *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8( + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0), kInterVar); if (*_vm->_global->_inter_execPtr == 13) { _vm->_global->_inter_execPtr++; diff --git a/engines/gob/parse_v2.cpp b/engines/gob/parse_v2.cpp index 65315c083a..a2e6b8fb37 100644 --- a/engines/gob/parse_v2.cpp +++ b/engines/gob/parse_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -409,8 +408,8 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) { else if (operation == 27) *valPtr = (int16) READ_VARO_UINT16(temp * 2 + offset * 2); else if (operation == 28) { - *valPtr = encodePtr(_vm->_global->_inter_variables + - temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, + *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8( + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0), kInterVar); if (*_vm->_global->_inter_execPtr == 13) { _vm->_global->_inter_execPtr++; @@ -468,7 +467,7 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) { case 25: *operPtr = 22; temp = _vm->_inter->load16() * 4; - *valPtr = encodePtr(_vm->_global->_inter_variables + temp, kInterVar); + *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp, 0), kInterVar); if (*_vm->_global->_inter_execPtr == 13) { _vm->_global->_inter_execPtr++; temp += parseValExpr(12); diff --git a/engines/gob/saveload.cpp b/engines/gob/saveload.cpp index 717bc143a6..2788716858 100644 --- a/engines/gob/saveload.cpp +++ b/engines/gob/saveload.cpp @@ -24,456 +24,714 @@ */ #include "common/endian.h" -#include "common/file.h" +#include "common/savefile.h" #include "gob/gob.h" #include "gob/saveload.h" -#include "gob/global.h" #include "gob/draw.h" -#include "gob/video.h" namespace Gob { -SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) { - _curSlot = -1; +TempSprite::TempSprite() { + _sprite = 0; + _width = _height = 0; + _size = -1; + memset(_palette, 0, 768); +} - _stagesCount = 0; - _buffer = 0; +TempSprite::~TempSprite() { + delete[] _sprite; +} - _tempSprite = 0; - memset(_tempPal, 0, 768); - _tempSpriteSize = -1; +int TempSprite::getSpriteIndex(int32 size) const { + if (size < -1000) + size += 1000; - _saveFiles = new char*[5]; + return -size - 1; +} - assert(_saveFiles); +bool TempSprite::getSpritePalette(int32 size) const { + return size < -1000; +} - _saveFiles[0] = new char[strlen(targetName) + 5]; - _saveFiles[1] = 0; - _saveFiles[2] = new char[strlen(targetName) + 5]; - _saveFiles[3] = _saveFiles[0]; - _saveFiles[4] = 0; +bool TempSprite::getProperties(int16 dataVar, int32 size, int32 offset, + int &index, bool &palette) const { - assert(_saveFiles[0] && _saveFiles[2]); + if (size >= 0) { + warning("Invalid index (%d)", size); + return false; + } - sprintf(_saveFiles[0], "%s.s00", targetName); - sprintf(_saveFiles[2], "%s.blo", targetName); -} + index = getSpriteIndex(size); + palette = getSpritePalette(size); -SaveLoad::~SaveLoad() { - if (_buffer) { - for (int i = 0; i < _stagesCount; i++) - delete[] _buffer[i]; - delete[] _buffer; + if ((index < 0) || (index >= SPRITES_COUNT)) { + warning("Index out of range (%d)", index); + return false; } - delete _tempSprite; + return true; +} - delete[] _saveFiles[0]; - delete[] _saveFiles[2]; - delete[] _saveFiles; +int32 TempSprite::getSize() const { + return _size; } -const char *SaveLoad::setCurSlot(int slot) { - static char *slotBase = _saveFiles[0] + strlen(_saveFiles[0]) - 2; +bool TempSprite::saveSprite(const SurfaceDesc &surfDesc) { + delete[] _sprite; + + _width = surfDesc.getWidth(); + _height = surfDesc.getHeight(); + _size = _width * _height; + _sprite = new byte[_size]; - if (_curSlot != slot) { - _curSlot = slot; + memcpy(_sprite, surfDesc.getVidMem(), _size); - if (_curSlot >= 0) - snprintf(slotBase, 3, "%02d", slot); + return true; +} + +bool TempSprite::savePalette(const Video::Color *palette) { + memcpy((byte *) _palette, (byte *) palette, 768); + return true; +} + +bool TempSprite::loadSprite(SurfaceDesc &surfDesc) { + if (!_sprite) { + warning("No sprite saved"); + return false; + } + + if (_size != (surfDesc.getWidth() * surfDesc.getHeight())) { + warning("Dimensions don't match (%dx%d - %dx%d", + _width, _height, surfDesc.getWidth(), surfDesc.getHeight()); + return false; } - return _saveFiles[0]; + memcpy(surfDesc.getVidMem(), _sprite, _size); + + return true; } -uint32 SaveLoad::read(Common::ReadStream &in, byte *buf, - byte *sizes, uint32 count) { - uint32 nRead; +bool TempSprite::loadPalette(Video::Color *palette) { + memcpy((byte *) palette, (byte *) _palette, 768); + return true; +} - nRead = in.read(buf, count); - if (nRead != count) { - warning("Can't read data: requested %d, got %d", count, nRead); - return 0; +bool TempSprite::toBuffer(byte *buffer, int32 size, bool palette) const { + + int32 haveSize = _size + (palette ? 768 : 0); + if (size != haveSize) { + warning("Sizes don't match (%d != %d)", size, haveSize); + return false; } - nRead = in.read(sizes, count); - if (nRead != count) { - warning("Can't read data sizes: requested %d, got %d", count, nRead); - return 0; + if (palette) { + memcpy(buffer, (byte *) _palette, 768); + buffer += 768; } - return count; + memcpy(buffer, _sprite, _size); + + return true; } -uint32 SaveLoad::write(Common::WriteStream &out, byte *buf, - byte *sizes, uint32 count) { - uint32 written; +bool TempSprite::fromBuffer(const byte *buffer, int32 size, bool palette) { + if (palette) { + memcpy((byte *) _palette, buffer, 768); + buffer += 768; + size -= 768; + } - written = out.write(buf, count); - if (written != count) { - warning("Can't write data: requested %d, wrote %d", count, written); - return 0; + _size = size; + + delete[] _sprite; + _sprite = new byte[_size]; + + memcpy(_sprite, buffer, _size); + + return true; +} + + +PlainSave::PlainSave() { +} + +PlainSave::~PlainSave() { +} + +bool PlainSave::save(int16 dataVar, int32 size, int32 offset, const char *name, + const Variables *variables) { + + if ((size <= 0) || (offset != 0)) { + warning("Invalid size (%d) or offset (%d)", size, offset); + return false; } - written = out.write(sizes, count); - if (written != count) { - warning("Can't write data: requested %d, wrote %d", count, written); - return 0; + byte *vars = new byte[size]; + byte *varSizes = new byte[size]; + + if (!variables->copyTo(dataVar, vars, varSizes, size)) { + delete[] vars; + delete[] varSizes; + warning("dataVar (%d) or size (%d) out of range", dataVar, size); + return false; } - return count; + bool result = save(0, size, offset, name, vars, varSizes); + + delete[] vars; + delete[] varSizes; + + return result; } -bool SaveLoad::loadDataEndian(Common::ReadStream &in, - int16 dataVar, uint32 size) { +bool PlainSave::load(int16 dataVar, int32 size, int32 offset, const char *name, + Variables *variables) { - bool retVal = false; + if ((size <= 0) || (offset != 0)) { + warning("Invalid size (%d) or offset (%d)", size, offset); + return false; + } - byte *varBuf = new byte[size]; - byte *sizeBuf = new byte[size]; + byte *vars = new byte[size]; + byte *varSizes = new byte[size]; - assert(varBuf && sizeBuf); + bool result = load(0, size, offset, name, vars, varSizes); - if (read(in, varBuf, sizeBuf, size) == size) { - if (fromEndian(varBuf, sizeBuf, size)) { - memcpy(_vm->_global->_inter_variables + dataVar, varBuf, size); - memcpy(_vm->_global->_inter_variablesSizes + dataVar, sizeBuf, size); - retVal = true; + if (result && variables) { + if (!variables->copyFrom(dataVar, vars, varSizes, size)) { + delete[] vars; + delete[] varSizes; + warning("dataVar (%d) or size (%d) out of range", dataVar, size); + return false; } } - delete[] varBuf; - delete[] sizeBuf; + delete[] vars; + delete[] varSizes; - return retVal; + return result; } -bool SaveLoad::saveDataEndian(Common::WriteStream &out, - int16 dataVar, uint32 size) { +bool PlainSave::save(int16 dataVar, int32 size, int32 offset, const char *name, + const byte *variables, const byte *variableSizes) const { - bool retVal = false; + if ((size <= 0) || (offset != 0)) { + warning("Invalid size (%d) or offset (%d)", size, offset); + return false; + } - byte *varBuf = new byte[size]; - byte *sizeBuf = new byte[size]; + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::OutSaveFile *out = saveMan->openForSaving(name); - assert(varBuf && sizeBuf); + if (!out) { + warning("Can't open file \"%s\" for writing", name); + return false; + } - memcpy(varBuf, _vm->_global->_inter_variables + dataVar, size); - memcpy(sizeBuf, _vm->_global->_inter_variablesSizes + dataVar, size); + bool retVal; + retVal = SaveLoad::saveDataEndian(*out, dataVar, size, variables, variableSizes); - if (toEndian(varBuf, sizeBuf, size)) - if (write(out, varBuf, sizeBuf, size) == size) - retVal = true; + out->finalize(); + if (out->ioFailed()) { + warning("Can't write to file \"%s\"", name); + retVal = false; + } - delete[] varBuf; - delete[] sizeBuf; + delete out; + return retVal; +} + +bool PlainSave::load(int16 dataVar, int32 size, int32 offset, const char *name, + byte *variables, byte *variableSizes) const { + + if ((size <= 0) || (offset != 0)) { + warning("Invalid size (%d) or offset (%d)", size, offset); + return false; + } + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in = saveMan->openForLoading(name); + + if (!in) { + warning("Can't open file \"%s\" for reading", name); + return false; + } + bool retVal = SaveLoad::loadDataEndian(*in, dataVar, size, variables, variableSizes); + delete in; return retVal; } -int32 SaveLoad::getSize(SaveType type) { - switch (type) { - case kSaveNone: - return -1; - break; - case kSaveGame: - return getSizeGame(); - break; +StagedSave::StagedSave() { + _mode = kModeNone; + _name = 0; + _loaded = false; +} - case kSaveTempSprite: - return getSizeTempSprite(); - break; +StagedSave::~StagedSave() { + clear(); +} - case kSaveNotes: - return getSizeNotes(); - break; +void StagedSave::addStage(int32 size, bool endianed) { + int32 offset = 0; - case kSaveScreenshot: - return getSizeScreenshot(); - break; + if (!_stages.empty()) + offset = _stages[_stages.size() - 1].offset + + _stages[_stages.size() - 1].size; - case kSaveIgnore: - return -1; - break; - } + Stage stage(size, offset, endianed); + _stages.push_back(stage); +} + +int StagedSave::findStage(int16 dataVar, int32 size, int32 offset) const { + for (uint i = 0; i < _stages.size(); i++) + if ((_stages[i].size == size) && + (_stages[i].offset == offset)) + return i; return -1; } -bool SaveLoad::load(SaveType type, int16 dataVar, int32 size, int32 offset) { - switch (type) { - case kSaveNone: - return false; - break; - - case kSaveGame: - return loadGame(dataVar, size, offset); - break; +bool StagedSave::allSaved() const { + for (uint i = 0; i < _stages.size(); i++) + if (!_stages[i].bufVar) + return false; - case kSaveTempSprite: - return loadTempSprite(dataVar, size, offset); - break; + return true; +} - case kSaveNotes: - return loadNotes(dataVar, size, offset); - break; +uint32 StagedSave::getSize() const { + uint32 size = 0; - case kSaveScreenshot: - return loadScreenshot(dataVar, size, offset); - break; + for (uint i = 0; i < _stages.size(); i++) { + if (_stages[i].endianed) + size += 2 * _stages[i].size; + else + size += _stages[i].size; + } + + return size; +} - case kSaveIgnore: - return true; - break; +void StagedSave::clear() { + for (uint i = 0; i < _stages.size(); i++) { + delete[] _stages[i].bufVar; + delete[] _stages[i].bufVarSizes; + _stages[i].bufVar = 0; + _stages[i].bufVarSizes = 0; } - return false; + delete[] _name; + _name = 0; + + _mode = kModeNone; + _loaded = false; } -bool SaveLoad::save(SaveType type, int16 dataVar, int32 size, int32 offset) { - switch (type) { - case kSaveNone: - return false; - break; +void StagedSave::assertMode(Mode mode, const char *name) { + if ((_mode != mode) || ((name[0] != '\0') && strcmp(_name, name))) { + clear(); + _mode = mode; + _name = new char[strlen(name) + 1]; + strcpy(_name, name); + } +} - case kSaveGame: - return saveGame(dataVar, size, offset); - break; +bool StagedSave::save(int16 dataVar, int32 size, int32 offset, const char *name, + const Variables *variables) { - case kSaveTempSprite: - return saveTempSprite(dataVar, size, offset); - break; + if ((dataVar < 0) || (size <= 0) || (offset < 0)) { + warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset); + return false; + } - case kSaveNotes: - return saveNotes(dataVar, size, offset); - break; + byte *vars = 0, *varSizes = 0; - case kSaveScreenshot: - return saveScreenshot(dataVar, size, offset); - break; + if (variables) { + vars = new byte[size]; + varSizes = new byte[size]; - case kSaveIgnore: - return true; - break; + if (!variables->copyTo(dataVar, vars, varSizes, size)) { + delete[] vars; + delete[] varSizes; + warning("dataVar (%d) or size (%d) out of range", dataVar, size); + return false; + } } - return false; -} + bool result = save(0, size, offset, name, vars, varSizes); + + delete[] vars; + delete[] varSizes; -int32 SaveLoad::getSizeTempSprite() { - return _tempSpriteSize; + return result; } -bool SaveLoad::loadTempSprite(int16 dataVar, int32 size, int32 offset) { - int index; - bool readPal; +bool StagedSave::load(int16 dataVar, int32 size, int32 offset, const char *name, + Variables *variables) { - if (size >= 0) { - warning("Invalid attempt at loading from the temporary sprite"); + if ((dataVar < 0) || (size <= 0) || (offset < 0)) { + warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset); return false; } - index = getSpriteIndex(size); - readPal = getSpritePalette(size); + byte *vars = new byte[size]; + byte *varSizes = new byte[size]; - if ((index < 0) || (index >= SPRITES_COUNT)) { - warning("Index out of range while loading from the temporary " - "sprite (%d)", index); - return false; + bool result = load(0, size, offset, name, vars, varSizes); + + if (result && variables) { + if (!variables->copyFrom(dataVar, vars, varSizes, size)) { + delete[] vars; + delete[] varSizes; + warning("dataVar (%d) or size (%d) out of range", dataVar, size); + return false; + } } - return loadTempSprite(index, readPal); + delete[] vars; + delete[] varSizes; + + return result; } -bool SaveLoad::saveTempSprite(int16 dataVar, int32 size, int32 offset) { - int index; - bool readPal; +bool StagedSave::save(int16 dataVar, int32 size, int32 offset, const char *name, + const byte *variables, const byte *variableSizes) { - if (size >= 0) { - warning("Invalid attempt at saving to the temporary sprite"); + if ((dataVar < 0) || (size <= 0) || (offset < 0)) { + warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset); return false; } - index = getSpriteIndex(size); - readPal = getSpritePalette(size); + int stage = findStage(dataVar, size, offset); + if (stage == -1) { + warning("Invalid saving procedure"); + return false; + } - if ((index < 0) || (index >= SPRITES_COUNT)) { - warning("Index out of range while saving to the temporary sprite (%d)", - index); + if (!variables || (_stages[stage].endianed && !variableSizes)) { + warning("Missing data"); return false; } - return saveTempSprite(index, readPal); -} + assertMode(kModeSave, name); -bool SaveLoad::loadTempSprite(uint32 index, bool palette) { - SurfaceDesc *sprite; + _stages[stage].bufVar = new byte[size]; + memcpy(_stages[stage].bufVar, variables + dataVar, size); - if (palette) { - memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, - (char *) _tempPal, 768); - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + if (_stages[stage].endianed) { + _stages[stage].bufVarSizes = new byte[size]; + memcpy(_stages[stage].bufVarSizes, variableSizes + dataVar, size); + } + + if (allSaved()) { + bool result = write(); + clear(); + return result; } - sprite = _vm->_draw->_spritesArray[index]; + return true; +} + +bool StagedSave::load(int16 dataVar, int32 size, int32 offset, const char *name, + byte *variables, byte *variableSizes) { - if (!sprite) { - warning("Couldn't load from the temporary sprite: " - "No such sprite %d", index); + if ((dataVar < 0) || (size <= 0) || (offset < 0)) { + warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset); return false; } - if ((sprite->getWidth() != _tempSprite->getWidth()) || - (sprite->getHeight() != _tempSprite->getHeight())) { - warning("Resolution doesn't match while loading from the " - "temporary sprite (%d: %dx%d vs. %dx%d)", index, - sprite->getWidth(), sprite->getHeight(), - _tempSprite->getWidth(), _tempSprite->getHeight()); + int stage = findStage(dataVar, size, offset); + if (stage == -1) { + warning("Invalid loading procedure"); return false; } - _vm->_video->drawSprite(_tempSprite, sprite, 0, 0, - sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0); + assertMode(kModeLoad, name); - if (index == 21) { - _vm->_draw->forceBlit(); - _vm->_video->retrace(); + if (!_loaded) { + if (!read()) { + clear(); + return false; + } } + if (variables) + memcpy(variables + dataVar, _stages[stage].bufVar, size); + if (_stages[stage].endianed && variableSizes) + memcpy(variableSizes + dataVar, _stages[stage].bufVarSizes, size); + return true; } -bool SaveLoad::saveTempSprite(uint32 index, bool palette) { - SurfaceDesc *sprite = _vm->_draw->_spritesArray[index]; +bool StagedSave::write() const { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::OutSaveFile *out = saveMan->openForSaving(_name); - if (!sprite) { - warning("Couldn't save to the temporary sprite: " - "No such sprite %d", index); + if (!out) { + warning("Can't open file \"%s\" for writing", _name); return false; } - delete _tempSprite; - _tempSprite = _vm->_video->initSurfDesc(_vm->_global->_videoMode, - sprite->getWidth(), sprite->getHeight(), 0); + bool result = true; + for (uint i = 0; (i < _stages.size()) && result; i++) { + if (!_stages[i].endianed) { - _vm->_video->drawSprite(sprite, _tempSprite, 0, 0, - sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0); + uint32 written = out->write(_stages[i].bufVar, _stages[i].size); - _tempSpriteSize = _vm->_draw->getSpriteRectSize(index); + result = (written == ((uint32) _stages[i].size)); + if (!result) + warning("Can't write data: requested %d, wrote %d", _stages[i].size, written); - if (palette) { - memcpy((char *) _tempPal, - (char *) _vm->_global->_pPaletteDesc->vgaPal, 768); - _tempSpriteSize += 768; + } else + result = SaveLoad::saveDataEndian(*out, 0, _stages[i].size, + _stages[i].bufVar, _stages[i].bufVarSizes); } - return true; + if (result) { + out->finalize(); + if (out->ioFailed()) { + warning("Can't write to file \"%s\"", _name); + result = false; + } + } + + delete out; + return result; } -bool SaveLoad::loadSprite(Common::ReadStream &in, int32 size) { - SurfaceDesc *sprite; - byte *buf; - int nRead; - int index; - bool readPal; +bool StagedSave::read() { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in = saveMan->openForLoading(_name); - if (size >= 0) { - warning("Invalid attempt at loading a sprite"); + if (!in) { + warning("Can't open file \"%s\" for reading", _name); return false; } - index = getSpriteIndex(size); - readPal = getSpritePalette(size); - - if ((index < 0) || (index >= SPRITES_COUNT)) { - warning("Index out of range while loading a sprite (%d)", - index); + uint32 saveSize = getSize(); + if (in->size() != saveSize) { + warning("Wrong size (%d != %d)", in->size(), saveSize); return false; } - size = _vm->_draw->getSpriteRectSize(index); - sprite = _vm->_draw->_spritesArray[index]; + bool result = true; + for (uint i = 0; ((i < _stages.size()) && result); i++) { + _stages[i].bufVar = new byte[_stages[i].size]; - if (!sprite) { - warning("Couldn't load sprite: No such sprite %d", index); - return false; - } + if (!_stages[i].endianed) { - buf = new byte[MAX<int>(768, size)]; - assert(buf); + uint32 nRead = in->read(_stages[i].bufVar, _stages[i].size); - if (readPal) { - nRead = in.read(buf, 768); - if (nRead != 768) { - warning("Couldn't read a palette: requested 768, got %d", nRead); - delete[] buf; - return false; - } + result = (nRead == ((uint32) _stages[i].size)); + if (!result) + warning("Can't read data: requested %d, got %d", _stages[i].size, nRead); - memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, - (char *) buf, 768); - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - } + } else { + _stages[i].bufVarSizes = new byte[_stages[i].size]; - nRead = in.read(buf, size); - if (nRead != size) { - warning("Couldn't read sprite data: requested %d, got %d", size, nRead); - delete[] buf; - return false; + result = SaveLoad::loadDataEndian(*in, 0, _stages[i].size, + _stages[i].bufVar, _stages[i].bufVarSizes); + } } - memcpy((char *) sprite->getVidMem(), buf, size); + if (result) + _loaded = true; + + delete in; + return result; +} + + +PagedBuffer::PagedBuffer(uint32 pageSize) { + + _size = 0; + _pageSize = pageSize; +} + +PagedBuffer::~PagedBuffer() { + clear(); +} + +bool PagedBuffer::empty() const { + return _pages.empty(); +} + +uint32 PagedBuffer::getSize() const { + return _size; +} + +void PagedBuffer::clear() { + for (uint i = 0; i < _pages.size(); i++) + delete[] _pages[i]; + _pages.clear(); + _size = 0; +} + +bool PagedBuffer::write(const byte *buffer, uint32 size, uint32 offset) { + grow(size, offset); + + uint page = offset / _pageSize; + while (size > 0) { + if (!_pages[page]) + _pages[page] = new byte[_pageSize]; + + uint32 pStart = offset % _pageSize; + uint32 n = MIN(size, _pageSize - pStart); + + memcpy(_pages[page] + pStart, buffer, n); + + buffer += n; + offset += n; + size -= n; + page++; + } - delete[] buf; return true; } -bool SaveLoad::saveSprite(Common::WriteStream &out, int32 size) { - SurfaceDesc *sprite; - int written; - int index; - bool readPal; +bool PagedBuffer::read(byte *buffer, uint32 size, uint32 offset) const { + uint page = offset / _pageSize; - if (size >= 0) { - warning("Invalid attempt at saving a sprite"); - return false; + while (size > 0) { + if (offset >= _size) { + memset(buffer, 0, size); + break; + } + + uint32 pStart = offset % _pageSize; + uint32 n = MIN(MIN(size, _pageSize - pStart), _size - offset); + + if (_pages[page]) + memcpy(buffer, _pages[page] + pStart, n); + else + memset(buffer, 0, n); + + buffer += n; + offset += n; + size -= n; + page++; } - index = getSpriteIndex(size); - readPal = getSpritePalette(size); + return true; +} - if ((index < 0) || (index >= SPRITES_COUNT)) { - warning("Index out of range while saving a sprite (%d)", - index); - return false; +uint32 PagedBuffer::writeToStream(Common::WriteStream &out) const { + for (uint i = 0; i < _pages.size(); i++) { + if (!_pages[i]) { + for (uint32 j = 0; j < _pageSize; j++) + out.writeByte(0); + } else + out.write(_pages[i], _pageSize); } - size = _vm->_draw->getSpriteRectSize(index); - sprite = _vm->_draw->_spritesArray[index]; + return _size; +} + +uint32 PagedBuffer::readFromStream(Common::ReadStream &in) { + clear(); - if (!sprite) { - warning("Couldn't save sprite: No such sprite %d", index); - return false; + while (!in.eos()) { + byte *buffer = new byte[_pageSize]; + + _size += in.read(buffer, _pageSize); + + _pages.push_back(buffer); } - if (readPal) { - written = out.write((char *) _vm->_global->_pPaletteDesc->vgaPal, 768); - if (written != 768) { - warning("Couldn't write a palette: requested 768, wrote %d", written); - return false; - } + return _size; +} + +void PagedBuffer::grow(uint32 size, uint32 offset) { + uint32 eSize = offset + size; + + while (_size < eSize) { + _pages.push_back(0); + _size += MIN(_pageSize, eSize - _size); } +} + + +SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) { + + _targetName = new char[strlen(targetName) + 1]; + strcpy(_targetName, targetName); +} + +SaveLoad::~SaveLoad() { + delete[] _targetName; +} - written = out.write((char *) sprite->getVidMem(), size); - if (written != size) { - warning("Couldn't write a sprite: requested %d, wrote %d", - size, written); +int32 SaveLoad::getSize(const char *fileName) { + int type; + + type = getSaveType(stripPath(fileName)); + if (type == -1) + return -1; + + debugC(3, kDebugSaveLoad, "Requested size of save file \"%s\" (type %d)", + fileName, type); + + return getSizeVersioned(type); +} + +bool SaveLoad::load(const char *fileName, int16 dataVar, int32 size, int32 offset) { + int type; + + type = getSaveType(stripPath(fileName)); + if (type == -1) return false; - } - return true; + debugC(3, kDebugSaveLoad, "Requested loading of save file \"%s\" (type %d) - %d, %d, %d", + fileName, type, dataVar, size, offset); + + return loadVersioned(type, dataVar, size, offset); +} + +bool SaveLoad::save(const char *fileName, int16 dataVar, int32 size, int32 offset) { + int type; + + type = getSaveType(stripPath(fileName)); + if (type == -1) + return false; + + debugC(3, kDebugSaveLoad, "Requested saving of save file \"%s\" (type %d) - %d, %d, %d", + fileName, type, dataVar, size, offset); + + return saveVersioned(type, dataVar, size, offset); +} + +const char *SaveLoad::stripPath(const char *fileName) { + const char *backSlash; + if ((backSlash = strrchr(fileName, '\\'))) + return backSlash + 1; + + return fileName; +} + +char *SaveLoad::setCurrentSlot(char *destName, int slot) { + char *slotBase = destName + strlen(destName) - 2; + + snprintf(slotBase, 3, "%02d", slot); + + return destName; +} + +void SaveLoad::buildIndex(byte *buffer, char *name, int n, int32 size, int32 offset) { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + + for (int i = 0; i < n; i++, buffer += size) { + in = saveMan->openForLoading(setCurrentSlot(name, i)); + if (in) { + in->seek(offset); + in->read(buffer, size); + delete in; + } else + memset(buffer, 0, size); + } } bool SaveLoad::fromEndian(byte *buf, const byte *sizes, uint32 count) { @@ -514,4 +772,89 @@ bool SaveLoad::toEndian(byte *buf, const byte *sizes, uint32 count) { return true; } +uint32 SaveLoad::read(Common::ReadStream &in, + byte *buf, byte *sizes, uint32 count) { + uint32 nRead; + + nRead = in.read(buf, count); + if (nRead != count) { + warning("Can't read data: requested %d, got %d", count, nRead); + return 0; + } + + nRead = in.read(sizes, count); + if (nRead != count) { + warning("Can't read data sizes: requested %d, got %d", count, nRead); + return 0; + } + + return count; +} + +uint32 SaveLoad::write(Common::WriteStream &out, + const byte *buf, const byte *sizes, uint32 count) { + uint32 written; + + written = out.write(buf, count); + if (written != count) { + warning("Can't write data: requested %d, wrote %d", count, written); + return 0; + } + + written = out.write(sizes, count); + if (written != count) { + warning("Can't write data: requested %d, wrote %d", count, written); + return 0; + } + + return count; +} + +bool SaveLoad::loadDataEndian(Common::ReadStream &in, + int16 dataVar, uint32 size, byte *variables, byte *variableSizes) { + + bool retVal = false; + + byte *varBuf = new byte[size]; + byte *sizeBuf = new byte[size]; + + assert(varBuf && sizeBuf); + + if (read(in, varBuf, sizeBuf, size) == size) { + if (fromEndian(varBuf, sizeBuf, size)) { + memcpy(variables + dataVar, varBuf, size); + memcpy(variableSizes + dataVar, sizeBuf, size); + retVal = true; + } + } + + delete[] varBuf; + delete[] sizeBuf; + + return retVal; +} + +bool SaveLoad::saveDataEndian(Common::WriteStream &out, + int16 dataVar, uint32 size, const byte *variables, const byte *variableSizes) { + + bool retVal = false; + + byte *varBuf = new byte[size]; + byte *sizeBuf = new byte[size]; + + assert(varBuf && sizeBuf); + + memcpy(varBuf, variables + dataVar, size); + memcpy(sizeBuf, variableSizes + dataVar, size); + + if (toEndian(varBuf, sizeBuf, size)) + if (write(out, varBuf, sizeBuf, size) == size) + retVal = true; + + delete[] varBuf; + delete[] sizeBuf; + + return retVal; +} + } // End of namespace Gob diff --git a/engines/gob/saveload.h b/engines/gob/saveload.h index bf1e4c01a8..29f7ee2594 100644 --- a/engines/gob/saveload.h +++ b/engines/gob/saveload.h @@ -26,143 +26,380 @@ #ifndef GOB_SAVELOAD_H #define GOB_SAVELOAD_H +#include "common/array.h" #include "common/stream.h" #include "gob/video.h" +#include "gob/variables.h" namespace Gob { -enum SaveType { - kSaveNone = -1, - kSaveGame, - kSaveTempSprite, - kSaveNotes, - kSaveScreenshot, - kSaveIgnore +class TempSprite { +public: + TempSprite(); + ~TempSprite(); + + bool getProperties(int16 dataVar, int32 size, int32 offset, + int &index, bool &palette) const; + + int32 getSize() const; + + bool saveSprite(const SurfaceDesc &surfDesc); + bool savePalette(const Video::Color *palette); + bool loadSprite(SurfaceDesc &surfDesc); + bool loadPalette(Video::Color *palette); + + bool toBuffer(byte *buffer, int32 size, bool palette) const; + bool fromBuffer(const byte *buffer, int32 size, bool palette); + +private: + byte *_sprite; + int16 _width; + int16 _height; + int32 _size; + Video::Color _palette[256]; + + int getSpriteIndex(int32 size) const; + bool getSpritePalette(int32 size) const; }; -class SaveLoad { +class PlainSave { +public: + PlainSave(); + ~PlainSave(); + + bool save(int16 dataVar, int32 size, int32 offset, const char *name, + const Variables *variables); + bool load(int16 dataVar, int32 size, int32 offset, const char *name, + Variables *variables); + + bool save(int16 dataVar, int32 size, int32 offset, const char *name, + const byte *variables, const byte *variableSizes) const; + bool load(int16 dataVar, int32 size, int32 offset, const char *name, + byte *variables, byte *variableSizes) const; +}; + +class StagedSave { public: - int32 getSize(SaveType type); - bool load(SaveType type, int16 dataVar, int32 size, int32 offset); - bool save(SaveType type, int16 dataVar, int32 size, int32 offset); + StagedSave(); + ~StagedSave(); + + void addStage(int32 size, bool endianed = true); - virtual SaveType getSaveType(const char *fileName) = 0; + bool save(int16 dataVar, int32 size, int32 offset, const char *name, + const Variables *variables); + bool load(int16 dataVar, int32 size, int32 offset, const char *name, + Variables *variables); + + bool save(int16 dataVar, int32 size, int32 offset, const char *name, + const byte *variables, const byte *variableSizes); + bool load(int16 dataVar, int32 size, int32 offset, const char *name, + byte *variables, byte *variableSizes); + +private: + struct Stage { + byte *bufVar; + byte *bufVarSizes; + int32 size; + int32 offset; + bool endianed; + + Stage(int32 s = 0, int32 off = 0, bool end = true) : + bufVar(0), bufVarSizes(0), size(s), offset(off), endianed(end) {} + }; + + enum Mode { + kModeNone, + kModeSave, + kModeLoad + }; + + Common::Array<Stage> _stages; + enum Mode _mode; + char *_name; + + bool _loaded; + + int findStage(int16 dataVar, int32 size, int32 offset) const; + bool allSaved() const; + + uint32 getSize() const; + + void clear(); + void assertMode(Mode mode, const char *name); + + bool write() const; + bool read(); +}; + +class PagedBuffer { +public: + PagedBuffer(uint32 pageSize = 1024); + ~PagedBuffer(); + + bool empty() const; + uint32 getSize() const; + + void clear(); + + bool write(const byte *buffer, uint32 size, uint32 offset); + bool read(byte *buffer, uint32 size, uint32 offset) const; + + uint32 writeToStream(Common::WriteStream &out) const; + uint32 readFromStream(Common::ReadStream &in); + +private: + uint32 _size; + uint32 _pageSize; + Common::Array<byte *> _pages; + + void grow(uint32 size, uint32 offset); +}; + +class SaveLoad { +public: + enum SaveMode { + kSaveModeNone, + kSaveModeIgnore, + kSaveModeSave + }; SaveLoad(GobEngine *vm, const char *targetName); virtual ~SaveLoad(); -protected: - int _curSlot; - char **_saveFiles; + virtual SaveMode getSaveMode(const char *fileName) = 0; - int _stagesCount; - byte **_buffer; + int32 getSize(const char *fileName); + bool load(const char *fileName, int16 dataVar, int32 size, int32 offset); + bool save(const char *fileName, int16 dataVar, int32 size, int32 offset); - // While using the notepad or changing the font, the original executable - // temporarily dumps Draw::_backSurface to a file. Since that's not really - // a nice thing to do, we work around it. - SurfaceDesc *_tempSprite; - Video::Color _tempPal[256]; - int32 _tempSpriteSize; + char *setCurrentSlot(char *destName, int slot); + void buildIndex(byte *buffer, char *name, int n, int32 size, int32 offset = 0); + static const char *stripPath(const char *fileName); + + static bool fromEndian(byte *buf, const byte *sizes, uint32 count); + static bool toEndian(byte *buf, const byte *sizes, uint32 count); + static uint32 read(Common::ReadStream &in, + byte *buf, byte *sizes, uint32 count); + static uint32 write(Common::WriteStream &out, + const byte *buf, const byte *sizes, uint32 count); + + static bool loadDataEndian(Common::ReadStream &in, + int16 dataVar, uint32 size, byte *variables, byte *variableSizes); + static bool saveDataEndian(Common::WriteStream &out, + int16 dataVar, uint32 size, const byte *variables, const byte *variableSizes); + +protected: GobEngine *_vm; - int getSpriteIndex(int32 size) { - if (size < -1000) - size += 1000; - - return -size - 1; - } - bool getSpritePalette(int32 size) { - return size < -1000; - } - - const char *setCurSlot(int slot); - bool fromEndian(byte *buf, const byte *sizes, uint32 count); - bool toEndian(byte *buf, const byte *sizes, uint32 count); - uint32 read(Common::ReadStream &in, byte *buf, - byte *sizes, uint32 count); - uint32 write(Common::WriteStream &out, byte *buf, - byte *sizes, uint32 count); - - bool loadDataEndian(Common::ReadStream &in, int16 dataVar, uint32 size); - bool saveDataEndian(Common::WriteStream &out, int16 dataVar, uint32 size); - - bool loadTempSprite(uint32 index, bool palette); - bool saveTempSprite(uint32 index, bool palette); - bool loadSprite(Common::ReadStream &in, int32 size); - bool saveSprite(Common::WriteStream &out, int32 size); - - int32 getSizeTempSprite(); - bool loadTempSprite(int16 dataVar, int32 size, int32 offset); - bool saveTempSprite(int16 dataVar, int32 size, int32 offset); - - virtual uint32 getSaveGameSize() = 0; - - virtual int32 getSizeGame() = 0; - virtual int32 getSizeNotes() = 0; - virtual int32 getSizeScreenshot() = 0; - virtual bool loadGame(int16 dataVar, int32 size, int32 offset) = 0; - virtual bool loadNotes(int16 dataVar, int32 size, int32 offset) = 0; - virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset) = 0; - virtual bool saveGame(int16 dataVar, int32 size, int32 offset) = 0; - virtual bool saveNotes(int16 dataVar, int32 size, int32 offset) = 0; - virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset) = 0; + char *_targetName; + + virtual int getSaveType(const char *fileName) = 0; + + virtual int32 getSizeVersioned(int type) = 0; + virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset) = 0; + virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset) = 0; }; class SaveLoad_v2 : public SaveLoad { public: - virtual SaveType getSaveType(const char *fileName); + enum SaveType { + kSaveGame, + kSaveTempSprite, + kSaveNotes + }; SaveLoad_v2(GobEngine *vm, const char *targetName); - virtual ~SaveLoad_v2() {} + virtual ~SaveLoad_v2(); + + virtual SaveMode getSaveMode(const char *fileName); protected: - virtual uint32 getSaveGameSize(); - - virtual int32 getSizeGame(); - virtual int32 getSizeNotes(); - virtual int32 getSizeScreenshot(); - virtual bool loadGame(int16 dataVar, int32 size, int32 offset); - virtual bool loadNotes(int16 dataVar, int32 size, int32 offset); - virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset); - virtual bool saveGame(int16 dataVar, int32 size, int32 offset); - virtual bool saveNotes(int16 dataVar, int32 size, int32 offset); - virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset); - - void initBuffer(); + struct SaveFile { + const char *sourceName; + char *destName; + SaveMode mode; + SaveType type; + }; + + static SaveFile _saveFiles[]; + + int32 _varSize; + + TempSprite _tmpSprite; + PlainSave _notes; + StagedSave _save; + + byte _indexBuffer[600]; + bool _hasIndex; + + virtual int getSaveType(const char *fileName); + + virtual int32 getSizeVersioned(int type); + virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset); + virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset); + + int getSlot(int32 offset) const; + int getSlotRemainder(int32 offset) const; + + int32 getSizeGame(SaveFile &saveFile); + int32 getSizeTempSprite(SaveFile &saveFile); + int32 getSizeNotes(SaveFile &saveFile); + + bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + + bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + + void assertInited(); }; -class SaveLoad_v3 : public SaveLoad_v2 { -public: - virtual SaveType getSaveType(const char *fileName); +enum SaveType { + kSaveNone = -1, + kSaveGame, + kSaveTempSprite, + kSaveNotes, + kSaveScreenshot, + kSaveIgnore +}; - SaveLoad_v3(GobEngine *vm, const char *targetName, uint32 screenshotSize = 19968, +class SaveLoad_v3 : public SaveLoad { +public: + enum SaveType { + kSaveNone, + kSaveGame, + kSaveTempSprite, + kSaveNotes, + kSaveScreenshot + }; + + SaveLoad_v3(GobEngine *vm, const char *targetName, + uint32 screenshotSize = 19968, int32 indexOffset = 40, int32 screenshotOffset = 80); - virtual ~SaveLoad_v3() {} + virtual ~SaveLoad_v3(); + + virtual SaveMode getSaveMode(const char *fileName); protected: + struct SaveFile { + const char *sourceName; + char *destName; + SaveMode mode; + SaveType type; + int slot; + }; + bool _useScreenshots; bool _firstSizeGame; - int8 _saveSlot; uint32 _screenshotSize; int32 _indexOffset; int32 _screenshotOffset; - virtual uint32 getSaveGameSize(); + static SaveFile _saveFiles[]; + + int32 _varSize; + + TempSprite _screenshot; + TempSprite _tmpSprite; + PlainSave _notes; + StagedSave _save; + + byte _propBuffer[1000]; + byte _indexBuffer[1200]; + bool _hasIndex; + + virtual int getSaveType(const char *fileName); + + virtual int32 getSizeVersioned(int type); + virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset); + virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset); + + int getSlot(int32 offset) const; + int getSlotRemainder(int32 offset) const; + + int32 getSizeGame(SaveFile &saveFile); + int32 getSizeTempSprite(SaveFile &saveFile); + int32 getSizeNotes(SaveFile &saveFile); + int32 getSizeScreenshot(SaveFile &saveFile); + + bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadScreenshot(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + + bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveScreenshot(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + + void assertInited(); + + void buildScreenshotIndex(byte *buffer, char *name, int n); +}; + +class SaveLoad_v4 : public SaveLoad { +public: + enum SaveType { + kSaveNone, + kSaveScreenProps, + kSaveGame, + kSaveGameScreenProps + }; + + bool _firstSizeGame; + + SaveLoad_v4(GobEngine *vm, const char *targetName); + virtual ~SaveLoad_v4(); + + virtual SaveMode getSaveMode(const char *fileName); + +protected: + struct SaveFile { + const char *sourceName; + char *destName; + SaveMode mode; + SaveType type; + }; + + static SaveFile _saveFiles[]; + + int32 _varSize; + + StagedSave _save; + + byte _propBuffer[1000]; + byte _indexBuffer[1200]; + bool _hasIndex; + + byte *_screenProps; + + virtual int getSaveType(const char *fileName); + + virtual int32 getSizeVersioned(int type); + virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset); + virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset); + + int getSlot(int32 offset) const; + int getSlotRemainder(int32 offset) const; + + int32 getSizeScreenProps(SaveFile &saveFile); + int32 getSizeGame(SaveFile &saveFile); + int32 getSizeGameScreenProps(SaveFile &saveFile); + + bool loadScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool loadGameScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); - virtual int32 getSizeGame(); - virtual int32 getSizeScreenshot(); - virtual bool loadGame(int16 dataVar, int32 size, int32 offset); - virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset); - virtual bool saveGame(int16 dataVar, int32 size, int32 offset); - virtual bool saveNotes(int16 dataVar, int32 size, int32 offset); - virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset); + bool saveScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); + bool saveGameScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset); - bool saveGame(int32 screenshotSize); - void initBuffer(); + void assertInited(); }; } // End of namespace Gob diff --git a/engines/gob/saveload_v2.cpp b/engines/gob/saveload_v2.cpp index ab7211b216..a92fe8cf01 100644 --- a/engines/gob/saveload_v2.cpp +++ b/engines/gob/saveload_v2.cpp @@ -24,273 +24,344 @@ */ #include "common/endian.h" -#include "common/file.h" +#include "common/savefile.h" #include "gob/gob.h" #include "gob/saveload.h" #include "gob/global.h" #include "gob/game.h" +#include "gob/draw.h" +#include "gob/inter.h" namespace Gob { +SaveLoad_v2::SaveFile SaveLoad_v2::_saveFiles[] = { + { "cat.inf", 0, kSaveModeSave, kSaveGame}, + { "cat.cat", 0, kSaveModeSave, kSaveGame}, + { "save.inf", 0, kSaveModeSave, kSaveTempSprite}, + { "bloc.inf", 0, kSaveModeSave, kSaveNotes} +}; + SaveLoad_v2::SaveLoad_v2(GobEngine *vm, const char *targetName) : - SaveLoad(vm, targetName) { + SaveLoad(vm, targetName) { + + _saveFiles[0].destName = new char[strlen(targetName) + 5]; + _saveFiles[1].destName = _saveFiles[0].destName; + _saveFiles[2].destName = 0; + _saveFiles[3].destName = new char[strlen(targetName) + 5]; - _stagesCount = 1; + sprintf(_saveFiles[0].destName, "%s.s00", targetName); + sprintf(_saveFiles[3].destName, "%s.blo", targetName); + + _varSize = 0; + _hasIndex = false; } -SaveType SaveLoad_v2::getSaveType(const char *fileName) { - const char *backSlash; - if ((backSlash = strrchr(fileName, '\\'))) - fileName = backSlash + 1; - - if (!scumm_stricmp(fileName, "cat.inf")) - return kSaveGame; - if (!scumm_stricmp(fileName, "cat.cat")) - return kSaveGame; - if (!scumm_stricmp(fileName, "save.inf")) - return kSaveTempSprite; - if (!scumm_stricmp(fileName, "bloc.inf")) - return kSaveNotes; - - return kSaveNone; +SaveLoad_v2::~SaveLoad_v2() { + delete[] _saveFiles[0].destName; + delete[] _saveFiles[3].destName; } -uint32 SaveLoad_v2::getSaveGameSize() { - return 80 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2; +SaveLoad::SaveMode SaveLoad_v2::getSaveMode(const char *fileName) { + fileName = stripPath(fileName); + + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return _saveFiles[i].mode; + + return kSaveModeNone; } -int32 SaveLoad_v2::getSizeNotes() { - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::InSaveFile *in; - int32 size = -1; +int SaveLoad_v2::getSaveType(const char *fileName) { + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return i; - in = saveMan->openForLoading(_saveFiles[(int) kSaveNotes]); - if (in) { - size = in->size(); - delete in; + return -1; +} + +int32 SaveLoad_v2::getSizeVersioned(int type) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveGame: + return getSizeGame(_saveFiles[type]); + case kSaveTempSprite: + return getSizeTempSprite(_saveFiles[type]); + case kSaveNotes: + return getSizeNotes(_saveFiles[type]); } - return size; + return -1; } -int32 SaveLoad_v2::getSizeGame() { +bool SaveLoad_v2::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveGame: + if (loadGame(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading from slot %d", getSlot(offset)); + break; + + case kSaveTempSprite: + if(loadTempSprite(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading the temporary sprite"); + break; + + case kSaveNotes: + if (loadNotes(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading the notes"); + break; + } + + return false; +} + +bool SaveLoad_v2::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveGame: + if (saveGame(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving to slot %d", getSlot(offset)); + break; + + case kSaveTempSprite: + if(saveTempSprite(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving the temporary sprite"); + break; + + case kSaveNotes: + if (saveNotes(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving the notes"); + break; + } + + return false; +} + +int SaveLoad_v2::getSlot(int32 offset) const { + return ((offset - 600) / _varSize); +} + +int SaveLoad_v2::getSlotRemainder(int32 offset) const { + return ((offset - 600) % _varSize); +} + +int32 SaveLoad_v2::getSizeGame(SaveFile &saveFile) { Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::InSaveFile *in; for (int i = 14; i >= 0; i--) { - in = saveMan->openForLoading(setCurSlot(i)); + in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i)); if (in) { delete in; - return (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * - 4 + 600; + return (i + 1) * _varSize + 600; } } return -1; } -int32 SaveLoad_v2::getSizeScreenshot() { - return -1; +int32 SaveLoad_v2::getSizeTempSprite(SaveFile &saveFile) { + return _tmpSprite.getSize(); } -bool SaveLoad_v2::loadGame(int16 dataVar, int32 size, int32 offset) { +int32 SaveLoad_v2::getSizeNotes(SaveFile &saveFile) { Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::InSaveFile *in; - int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + int32 size = -1; + + in = saveMan->openForLoading(saveFile.destName); + if (in) { + size = in->size(); + delete in; + } + + return size; +} + +bool SaveLoad_v2::loadGame(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { if (size == 0) { dataVar = 0; - size = varSize; + size = _varSize; } - int slot = (offset - 600) / varSize; - int slotR = (offset - 600) % varSize; + if (offset == 0) { + debugC(3, kDebugSaveLoad, "Loading save index"); - if ((offset == 0) && (size == 600)) { - - byte *varBuf = _vm->_global->_inter_variables + dataVar; - for (int i = 0; i < 15; i++, varBuf += 40) { - in = saveMan->openForLoading(setCurSlot(i)); - if (in) { - in->read(varBuf, 40); - delete in; - } else - memset(varBuf, 0, 40); + if (size != 600) { + warning("Requested index has wrong size (%d)", size); + return false; } - memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 600); - return true; - } else if ((offset > 0) && (slot < 15) && - (slotR == 0) && (size == varSize)) { + SaveLoad::buildIndex(_vm->_inter->_variables->getAddressOff8(dataVar, 600), + saveFile.destName, 15, 40); + + } else { + int slot = getSlot(offset); + int slotRem = getSlotRemainder(offset); + + debugC(2, kDebugSaveLoad, "Loading from slot %d", slot); - in = saveMan->openForLoading(setCurSlot(slot)); - if (!in) { - warning("Can't open file for slot %d", slot); + SaveLoad::setCurrentSlot(saveFile.destName, slot); + + if ((slot >= 15) || (slotRem != 0)) { + warning("Invalid loading procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, slot, slotRem); return false; } - uint32 sGameSize = getSaveGameSize(); - uint32 fSize = in->size(); - if (fSize != sGameSize) { - warning("Can't load from slot %d: Wrong size (%d, %d)", slot, - fSize, sGameSize); - delete in; + if (!_save.load(dataVar, size, 40, saveFile.destName, _vm->_inter->_variables)) return false; - } + } - in->seek(80); - if (loadDataEndian(*in, dataVar, size)) { - delete in; - debugC(1, kDebugFileIO, "Loading from slot %d", slot); - return true; - } - delete in; + return true; +} - } else - warning("Invalid loading procedure (%d, %d, %d, %d)", - offset, size, slot, slotR); +bool SaveLoad_v2::loadTempSprite(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - return false; -} + debugC(3, kDebugSaveLoad, "Loading from the temporary sprite"); -bool SaveLoad_v2::loadNotes(int16 dataVar, int32 size, int32 offset) { - bool retVal; + int index; + bool palette; - if ((size <= 0) || (offset != 0)) { - warning("Invalid attempt at loading the notes (%d, %d)", size, offset); + if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette)) return false; - } - - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - char *sName = _saveFiles[(int) kSaveNotes]; - Common::InSaveFile *in = saveMan->openForLoading(sName); - if (!in) { - warning("Can't open file \"%s\" for reading", sName); + if (!_tmpSprite.loadSprite(*_vm->_draw->_spritesArray[index])) return false; + + if (palette) { + if (!_tmpSprite.loadPalette(_vm->_global->_pPaletteDesc->vgaPal)) + return false; + + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); } - retVal = loadDataEndian(*in, dataVar, size); - delete in; - return retVal; -} + if (index == 21) { + _vm->_draw->forceBlit(); + _vm->_video->retrace(); + } -bool SaveLoad_v2::loadScreenshot(int16 dataVar, int32 size, int32 offset) { - return false; + return true; } -bool SaveLoad_v2::saveGame(int16 dataVar, int32 size, int32 offset) { - int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; +bool SaveLoad_v2::loadNotes(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + debugC(2, kDebugSaveLoad, "Loading the notes"); + + return _notes.load(dataVar, size, offset, saveFile.destName, _vm->_inter->_variables); +} - initBuffer(); +bool SaveLoad_v2::saveGame(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { if (size == 0) { dataVar = 0; - size = varSize; + size = _varSize; } - int slot = (offset - 600) / varSize; - int slotR = (offset - 600) % varSize; + if (offset == 0) { + debugC(3, kDebugSaveLoad, "Saving save index"); - if ((offset == 0) && (size == 600)) { + if (size != 600) { + warning("Requested index has wrong size (%d)", size); + return false; + } - delete[] _buffer[0]; - _buffer[0] = new byte[1200]; - assert(_buffer[0]); + _vm->_inter->_variables->copyTo(dataVar, _indexBuffer, 0, 600); + _hasIndex = true; - memcpy(_buffer[0], _vm->_global->_inter_variables + dataVar, 600); - memset(_buffer[0] + 600, 0, 600); + } else { + int slot = getSlot(offset); + int slotRem = getSlotRemainder(offset); - return true; + debugC(2, kDebugSaveLoad, "Saving to slot %d", slot); - } else if ((offset > 0) && (slot < 15) && - (slotR == 0) && (size == varSize)) { + SaveLoad::setCurrentSlot(saveFile.destName, slot); - if (!_buffer[0]) { - warning("Tried to save without writing the index first"); + if ((slot >= 15) || (slotRem != 0)) { + warning("Invalid saving procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, slot, slotRem); return false; } - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::OutSaveFile *out; - - out = saveMan->openForSaving(setCurSlot(slot)); - if (!out) { - warning("Can't open file for slot %d for writing", slot); - delete[] _buffer[0]; - _buffer[0] = 0; + if (!_hasIndex) { + warning("No index written yet"); return false; } - bool retVal = false; + _hasIndex = false; - if (out->write(_buffer[0] + slot * 40, 40) == 40) - if (out->write(_buffer[0] + 600 + slot * 40, 40) == 40) - if (saveDataEndian(*out, dataVar, size)) { - out->finalize(); - if (!out->ioFailed()) - retVal = true; - } - - if (!retVal) - warning("Can't save to slot %d", slot); - else - debugC(1, kDebugFileIO, "Saved to slot %d", slot); - - delete[] _buffer[0]; - _buffer[0] = 0; - delete out; + byte sizes[40]; + memset(sizes, 0, 40); + if(!_save.save(0, 40, 0, saveFile.destName, _indexBuffer + (slot * 40), sizes)) + return false; - return retVal; + if (!_save.save(dataVar, size, 40, saveFile.destName, _vm->_inter->_variables)) + return false; - } else - warning("Invalid saving procedure (%d, %d, %d, %d)", - offset, size, slot, slotR); + } - return false; + return true; } -bool SaveLoad_v2::saveNotes(int16 dataVar, int32 size, int32 offset) { - bool retVal; +bool SaveLoad_v2::saveTempSprite(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - if ((size <= 0) || (offset != 0)) { - warning("Invalid attempt at saving the notes (%d, %d)", size, offset); - return false; - } + debugC(3, kDebugSaveLoad, "Saving to the temporary sprite"); - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - char *sName = _saveFiles[(int) kSaveNotes]; + int index; + bool palette; - Common::OutSaveFile *out = saveMan->openForSaving(sName); - if (!out) { - warning("Can't open file \"%s\" for writing", sName); + if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette)) return false; - } - retVal = saveDataEndian(*out, dataVar, size); + if (!_tmpSprite.saveSprite(*_vm->_draw->_spritesArray[index])) + return false; - out->finalize(); - if (out->ioFailed()) { - warning("Can't save notes"); - retVal = false; - } + if (palette) + if (!_tmpSprite.savePalette(_vm->_global->_pPaletteDesc->vgaPal)) + return false; - delete out; - return retVal; + return true; } -bool SaveLoad_v2::saveScreenshot(int16 dataVar, int32 size, int32 offset) { +bool SaveLoad_v2::saveNotes(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + debugC(2, kDebugSaveLoad, "Saving the notes"); + + return _notes.save(dataVar, size, offset, saveFile.destName, _vm->_inter->_variables); return false; } -void SaveLoad_v2::initBuffer() { - if (_buffer) +void SaveLoad_v2::assertInited() { + if (_varSize > 0) return; - _buffer = new byte*[_stagesCount]; - assert(_buffer); - _buffer[0] = 0; + _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + + _save.addStage(40); + _save.addStage(_varSize); } } // End of namespace Gob diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp index 4a4036fded..67879db3d1 100644 --- a/engines/gob/saveload_v3.cpp +++ b/engines/gob/saveload_v3.cpp @@ -24,62 +24,181 @@ */ #include "common/endian.h" -#include "common/file.h" +#include "common/savefile.h" #include "gob/gob.h" #include "gob/saveload.h" #include "gob/global.h" #include "gob/game.h" +#include "gob/draw.h" +#include "gob/inter.h" namespace Gob { +SaveLoad_v3::SaveFile SaveLoad_v3::_saveFiles[] = { + { "cat.inf", 0, kSaveModeSave, kSaveGame, -1}, + { "ima.inf", 0, kSaveModeSave, kSaveScreenshot, -1}, + { "intro.$$$", 0, kSaveModeSave, kSaveTempSprite, -1}, + { "bloc.inf", 0, kSaveModeSave, kSaveNotes, -1}, + { "prot", 0, kSaveModeIgnore, kSaveNone, -1}, + { "config", 0, kSaveModeIgnore, kSaveNone, -1}, +}; + SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName, uint32 screenshotSize, int32 indexOffset, int32 screenshotOffset) : - SaveLoad_v2(vm, targetName) { + SaveLoad(vm, targetName) { _screenshotSize = screenshotSize; _indexOffset = indexOffset; _screenshotOffset = screenshotOffset; - _saveSlot = -1; - _stagesCount = 3; - _useScreenshots = false; _firstSizeGame = true; + + _saveFiles[0].destName = new char[strlen(targetName) + 5]; + _saveFiles[1].destName = _saveFiles[0].destName; + _saveFiles[2].destName = 0; + _saveFiles[3].destName = new char[strlen(targetName) + 5]; + _saveFiles[4].destName = 0; + _saveFiles[5].destName = 0; + + sprintf(_saveFiles[0].destName, "%s.s00", targetName); + sprintf(_saveFiles[3].destName, "%s.blo", targetName); + + _varSize = 0; + _hasIndex = false; + memset(_propBuffer, 0, 1000); } -SaveType SaveLoad_v3::getSaveType(const char *fileName) { - const char *backSlash; - if ((backSlash = strrchr(fileName, '\\'))) - fileName = backSlash + 1; - - if (!scumm_stricmp(fileName, "cat.inf")) - return kSaveGame; - if (!scumm_stricmp(fileName, "ima.inf")) - return kSaveScreenshot; - if (!scumm_stricmp(fileName, "intro.$$$")) - return kSaveTempSprite; - if (!scumm_stricmp(fileName, "bloc.inf")) - return kSaveNotes; - if (!scumm_stricmp(fileName, "prot")) - return kSaveIgnore; - if (!scumm_stricmp(fileName, "config")) - return kSaveIgnore; - - return kSaveNone; +SaveLoad_v3::~SaveLoad_v3() { + delete[] _saveFiles[0].destName; + delete[] _saveFiles[3].destName; } -uint32 SaveLoad_v3::getSaveGameSize() { - uint32 size; +SaveLoad::SaveMode SaveLoad_v3::getSaveMode(const char *fileName) { + fileName = stripPath(fileName); - size = 1040 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2; - if (_useScreenshots) - size += _screenshotSize; + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return _saveFiles[i].mode; - return size; + return kSaveModeNone; +} + +int SaveLoad_v3::getSaveType(const char *fileName) { + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return i; + + return -1; +} + +int32 SaveLoad_v3::getSizeVersioned(int type) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveGame: + return getSizeGame(_saveFiles[type]); + case kSaveTempSprite: + return getSizeTempSprite(_saveFiles[type]); + case kSaveNotes: + return getSizeNotes(_saveFiles[type]); + case kSaveScreenshot: + return getSizeScreenshot(_saveFiles[type]); + default: + break; + } + + return -1; +} + +bool SaveLoad_v3::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveGame: + if (loadGame(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading from slot %d", getSlot(offset)); + break; + + case kSaveTempSprite: + if(loadTempSprite(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading the temporary sprite"); + break; + + case kSaveNotes: + if (loadNotes(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading the notes"); + break; + + case kSaveScreenshot: + if (loadScreenshot(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading a screenshot"); + break; + + default: + break; + } + + return false; } -int32 SaveLoad_v3::getSizeGame() { +bool SaveLoad_v3::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveGame: + if (saveGame(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving to slot %d", getSlot(offset)); + break; + + case kSaveTempSprite: + if(saveTempSprite(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving the temporary sprite"); + break; + + case kSaveNotes: + if (saveNotes(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving the notes"); + break; + + case kSaveScreenshot: + if (saveScreenshot(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving a screenshot"); + break; + + default: + break; + } + + return false; +} + +int SaveLoad_v3::getSlot(int32 offset) const { + return ((offset - 1700) / _varSize); +} + +int SaveLoad_v3::getSlotRemainder(int32 offset) const { + return ((offset - 1700) % _varSize); +} + +int32 SaveLoad_v3::getSizeGame(SaveFile &saveFile) { if (_firstSizeGame) { _firstSizeGame = false; return -1; @@ -89,358 +208,403 @@ int32 SaveLoad_v3::getSizeGame() { Common::InSaveFile *in; int32 size = -1; - int slot = _curSlot; + int slot = saveFile.slot; for (int i = 29; i >= 0; i--) { - in = saveMan->openForLoading(setCurSlot(i)); + in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i)); if (in) { delete in; - size = (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * - 4 + 1700; + size = (i + 1) * _varSize + 1700; break; } } - setCurSlot(slot); + setCurrentSlot(saveFile.destName, slot); return size; } -int32 SaveLoad_v3::getSizeScreenshot() { +int32 SaveLoad_v3::getSizeTempSprite(SaveFile &saveFile) { + return _tmpSprite.getSize(); +} + +int32 SaveLoad_v3::getSizeNotes(SaveFile &saveFile) { Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::InSaveFile *in; int32 size = -1; - _useScreenshots = true; - int slot = _curSlot; + in = saveMan->openForLoading(saveFile.destName); + if (in) { + size = in->size(); + delete in; + } + + return size; +} + +int32 SaveLoad_v3::getSizeScreenshot(SaveFile &saveFile) { + if (!_useScreenshots) { + _useScreenshots = true; + _save.addStage(_screenshotSize, false); + } + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + int32 size = -1; + + int slot = saveFile.slot; for (int i = 29; i >= 0; i--) { - in = saveMan->openForLoading(setCurSlot(i)); + in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i)); if (in) { delete in; size = (i + 1) * _screenshotSize + _screenshotOffset; break; } } - setCurSlot(slot); + setCurrentSlot(saveFile.destName, slot); return size; } -bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) { - int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::InSaveFile *in; +bool SaveLoad_v3::loadGame(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - int slot = (offset - 1700) / varSize; - int slotR = (offset - 1700) % varSize; - - initBuffer(); + if (size == 0) { + dataVar = 0; + size = _varSize; + } - if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) { + if (offset < 500) { + debugC(3, kDebugSaveLoad, "Loading global properties"); - memcpy(_vm->_global->_inter_variables + dataVar, - _buffer[0] + offset, size); - memcpy(_vm->_global->_inter_variablesSizes + dataVar, - _buffer[0] + offset + 500, size); - return true; + if ((size + offset) > 500) { + warning("Wrong global properties list size (%d, %d)", size, offset); + return false; + } - } else if ((size == 1200) && (offset == 500)) { + _vm->_inter->_variables->copyFrom(dataVar, + _propBuffer + offset, _propBuffer + offset + 500, size); - memset(_buffer[1], 0, 1200); + } else if (offset == 500) { + debugC(3, kDebugSaveLoad, "Loading save index"); - slot = _curSlot; - for (int i = 0; i < 30; i++) { - in = saveMan->openForLoading(setCurSlot(i)); - if (in) { - in->seek(1000); - in->read(_buffer[1] + i * 40, 40); - delete in; - } + if (size != 1200) { + warning("Requested index has wrong size (%d)", size); + return false; } - setCurSlot(slot); - memcpy(_vm->_global->_inter_variables + dataVar, _buffer[1], 1200); - memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 1200); - return true; + int slot = saveFile.slot; + + SaveLoad::buildIndex(_vm->_inter->_variables->getAddressOff8(dataVar, 1200), + saveFile.destName, 30, 40, 1000); - } else if ((offset > 0) && (slot < 30) && - (slotR == 0) && (size == 0)) { + setCurrentSlot(saveFile.destName, slot); - in = saveMan->openForLoading(setCurSlot(slot)); - if (!in) { - warning("Can't open file for slot %d", slot); + } else { + saveFile.slot = getSlot(offset); + int slotRem = getSlotRemainder(offset); + + debugC(2, kDebugSaveLoad, "Loading from slot %d", saveFile.slot); + + SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot); + + if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) { + warning("Invalid loading procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, saveFile.slot, slotRem); return false; } - uint32 sGameSize = getSaveGameSize(); - uint32 fSize = in->size(); - if (fSize != sGameSize) { - warning("Can't load from slot %d: Wrong size (%d, %d)", slot, - fSize, sGameSize); - delete in; + if (!_save.load(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables)) return false; - } + } - byte varBuf[500], sizeBuf[500]; - if (read(*in, varBuf, sizeBuf, 500) == 500) { - if (fromEndian(varBuf, sizeBuf, 500)) { - memcpy(_buffer[0], varBuf, 500); - memcpy(_buffer[0] + 500, sizeBuf, 500); - in->seek(1040); - if (loadDataEndian(*in, 0, varSize)) { - delete in; - debugC(1, kDebugFileIO, "Loading from slot %d", slot); - return true; - } - } - } - delete in; + return true; +} - } else - warning("Invalid loading procedure (%d, %d, %d, %d)", - offset, size, slot, slotR); +bool SaveLoad_v3::loadTempSprite(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - return false; + debugC(3, kDebugSaveLoad, "Loading from the temporary sprite"); + + int index; + bool palette; + + if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette)) + return false; + + if (!_tmpSprite.loadSprite(*_vm->_draw->_spritesArray[index])) + return false; + + if (palette) { + if (!_tmpSprite.loadPalette(_vm->_global->_pPaletteDesc->vgaPal)) + return false; + + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + } + + if (index == 21) { + _vm->_draw->forceBlit(); + _vm->_video->retrace(); + } + + return true; } -bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) { - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::InSaveFile *in; +bool SaveLoad_v3::loadNotes(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - int slot = (offset - _screenshotOffset) / _screenshotSize; - int slotR = (offset - _screenshotOffset) % _screenshotSize; + debugC(2, kDebugSaveLoad, "Loading the notes"); - _useScreenshots = true; - if ((size == 40) && (offset == _indexOffset)) { - char buf[40]; + return _notes.load(dataVar, size, offset, saveFile.destName, _vm->_inter->_variables); +} - memset(buf, 0, 40); +bool SaveLoad_v3::loadScreenshot(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - slot = _curSlot; - for (int i = 0; i < 30; i++) { - in = saveMan->openForLoading(setCurSlot(i)); - if (in) { - delete in; - buf[i] = 1; - } + debugC(3, kDebugSaveLoad, "Loading a screenshot"); + + if (!_useScreenshots) { + _useScreenshots = true; + _save.addStage(_screenshotSize, false); + } + + if (offset == _indexOffset) { + if (size != 40) { + warning("Requested index has wrong size (%d)", size); + return false; } - setCurSlot(slot); - memcpy(_vm->_global->_inter_variables + dataVar, buf, 40); - memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 40); - return true; + byte buffer[40]; + memset(buffer, 0, 40); + + int slot = saveFile.slot; + buildScreenshotIndex(buffer, saveFile.destName, 30); + setCurrentSlot(saveFile.destName, slot); - } else if ((offset > 0) && (slot < 30) && - (slotR == 0) && (size < 0)) { + memcpy(_vm->_inter->_variables->getAddressOff8(dataVar, 40), buffer, 40); - int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + } else { + saveFile.slot = (offset - _screenshotOffset) / _screenshotSize; + int slotRem = (offset - _screenshotOffset) % _screenshotSize; - in = saveMan->openForLoading(setCurSlot(slot)); - if (!in) { - warning("Can't open file for slot %d", slot); + SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot); + + if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) { + warning("Invalid loading procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, saveFile.slot, slotRem); return false; } - uint32 sGameSize = getSaveGameSize(); - uint32 fSize = in->size(); - if (fSize != sGameSize) { - warning("Can't load screenshot from slot %d: Wrong size (%d, %d)", - slot, fSize, sGameSize); - delete in; + byte *buffer = new byte[_screenshotSize]; + + if (!_save.load(0, _screenshotSize, _varSize + 540, saveFile.destName, buffer, 0)) { + delete[] buffer; return false; } - in->seek(1040 + varSize * 2); + int index; + bool palette; - bool success = loadSprite(*in, size); - delete in; - return success; + if (!_screenshot.getProperties(dataVar, size, offset, index, palette)) { + delete[] buffer; + return false; + } - } else - warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)", - offset, size, slot, slotR); + if (!_screenshot.fromBuffer(buffer, _screenshotSize, palette)) { + delete[] buffer; + return false; + } - return false; -} + if (!_screenshot.loadSprite(*_vm->_draw->_spritesArray[index])) { + delete[] buffer; + return false; + } -bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) { - int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + if (palette) { + if (!_screenshot.loadPalette(_vm->_global->_pPaletteDesc->vgaPal)) { + delete[] buffer; + return false; + } + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + } + + delete[] buffer; + } - int slot = (offset - 1700) / varSize; - int slotR = (offset - 1700) % varSize; + return true; +} - initBuffer(); +bool SaveLoad_v3::saveGame(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) { + if (size == 0) { + dataVar = 0; + size = _varSize; + } - memcpy(_buffer[0] + offset, - _vm->_global->_inter_variables + dataVar, size); - memcpy(_buffer[0] + offset + 500, - _vm->_global->_inter_variablesSizes + dataVar, size); + if (offset < 500) { + debugC(3, kDebugSaveLoad, "Loading global properties"); - return true; + if ((size + offset) > 500) { + warning("Wrong global properties list size (%d, %d)", size, offset); + return false; + } - } else if ((size > 0) && (offset >= 500) && (offset < 1700) && - ((size + offset) <= 1700)) { + _vm->_inter->_variables->copyTo(dataVar, + _propBuffer + offset, _propBuffer + offset + 500, size); - memcpy(_buffer[1] + offset - 500, - _vm->_global->_inter_variables + dataVar, size); + } else if (offset == 500) { + debugC(3, kDebugSaveLoad, "Saving save index"); - return true; + if (size != 1200) { + warning("Requested index has wrong size (%d)", size); + return false; + } - } else if ((offset > 0) && (slot < 30) && - (slotR == 0) && (size == 0)) { + _vm->_inter->_variables->copyTo(dataVar, _indexBuffer, 0, size); + _hasIndex = true; - _saveSlot = -1; + } else { + saveFile.slot = getSlot(offset); + int slotRem = getSlotRemainder(offset); - delete _buffer[2]; - _buffer[2] = new byte[varSize * 2]; - assert(_buffer[2]); + debugC(2, kDebugSaveLoad, "Saving to slot %d", saveFile.slot); - memcpy(_buffer[2], _vm->_global->_inter_variables, varSize); - memcpy(_buffer[2] + varSize, - _vm->_global->_inter_variablesSizes, varSize); + SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot); - if (!toEndian(_buffer[2], _buffer[2] + varSize, varSize)) { - delete _buffer[2]; - _buffer[2] = 0; + if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) { + warning("Invalid saving procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, saveFile.slot, slotRem); return false; } - _saveSlot = slot; + if (!_hasIndex) { + warning("No index written yet"); + return false; + } - if (!_useScreenshots) - return saveGame(0); + _hasIndex = false; - return true; + if(!_save.save(0, 500, 0, saveFile.destName, _propBuffer, _propBuffer + 500)) + return false; - } else - warning("Invalid saving procedure (%d, %d, %d, %d)", - offset, size, slot, slotR); + if(!_save.save(0, 40, 500, saveFile.destName, _indexBuffer + (saveFile.slot * 40), 0)) + return false; - return false; -} + if (!_save.save(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables)) + return false; + + } -bool SaveLoad_v3::saveNotes(int16 dataVar, int32 size, int32 offset) { - return SaveLoad_v2::saveNotes(dataVar, size - 160, offset); + return true; } -bool SaveLoad_v3::saveScreenshot(int16 dataVar, int32 size, int32 offset) { - int slot = (offset - _screenshotOffset) / _screenshotSize; - int slotR = (offset - _screenshotOffset) % _screenshotSize; +bool SaveLoad_v3::saveTempSprite(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - _useScreenshots = true; + debugC(3, kDebugSaveLoad, "Saving to the temporary sprite"); - if ((offset < _screenshotOffset) && (size > 0)) { + int index; + bool palette; - return true; + if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette)) + return false; - } else if ((offset > 0) && (slot < 30) && - (slotR == 0) && (size < 0)) { + if (!_tmpSprite.saveSprite(*_vm->_draw->_spritesArray[index])) + return false; + + if (palette) + if (!_tmpSprite.savePalette(_vm->_global->_pPaletteDesc->vgaPal)) + return false; + + return true; +} - return saveGame(size); +bool SaveLoad_v3::saveNotes(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - } else - warning("Invalid attempt at saving a screenshot (%d, %d, %d, %d)", - offset, size, slot, slotR); + debugC(2, kDebugSaveLoad, "Saving the notes"); + return _notes.save(dataVar, size - 160, offset, saveFile.destName, _vm->_inter->_variables); return false; } -bool SaveLoad_v3::saveGame(int32 screenshotSize) { - int8 slot = _saveSlot; - - _saveSlot = -1; +bool SaveLoad_v3::saveScreenshot(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { - initBuffer(); + debugC(3, kDebugSaveLoad, "Saving a screenshot"); - if ((slot < 0) || (slot > 29)) { - warning("Can't save to slot %d: Out of range", slot); - delete[] _buffer[2]; - _buffer[2] = 0; - return false; + if (!_useScreenshots) { + _useScreenshots = true; + _save.addStage(_screenshotSize, false); } - if (!_buffer[2]) { - warning("Can't save to slot %d: No data", slot); - return false; - } + if (offset >= _screenshotOffset) { - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::OutSaveFile *out; + saveFile.slot = (offset - _screenshotOffset) / _screenshotSize; + int slotRem = (offset - _screenshotOffset) % _screenshotSize; - out = saveMan->openForSaving(setCurSlot(slot)); - if (!out) { - warning("Can't open file for slot %d for writing", slot); - delete[] _buffer[2]; - _buffer[2] = 0; - return false; - } + setCurrentSlot(saveFile.destName, saveFile.slot); + + if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) { + warning("Invalid saving procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, saveFile.slot, slotRem); + return false; + } - int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; - byte varBuf[500], sizeBuf[500]; + int index; + bool palette; - memcpy(varBuf, _buffer[0], 500); - memcpy(sizeBuf, _buffer[0] + 500, 500); + if (!_screenshot.getProperties(dataVar, size, offset, index, palette)) + return false; - bool retVal = false; - if (toEndian(varBuf, sizeBuf, 500)) - if (write(*out, varBuf, sizeBuf, 500) == 500) - if (out->write(_buffer[1] + slot * 40, 40) == 40) - if (out->write(_buffer[2], varSize * 2) == ((uint32) (varSize * 2))) { - out->flush(); - if (!out->ioFailed()) - retVal = true; - } + if (!_screenshot.saveSprite(*_vm->_draw->_spritesArray[index])) + return false; - delete[] _buffer[2]; - _buffer[2] = 0; + if (palette) + if (!_screenshot.savePalette(_vm->_global->_pPaletteDesc->vgaPal)) + return false; - if (!retVal) { - warning("Can't save to slot %d", slot); - delete out; - return false; - } + + byte *buffer = new byte[_screenshotSize]; - if (_useScreenshots) { - if (screenshotSize >= 0) { - warning("Can't save to slot %d: Screenshot expected", slot); - delete out; + if (!_screenshot.toBuffer(buffer, _screenshotSize, palette)) { + delete[] buffer; return false; } - if (!saveSprite(*out, screenshotSize)) { - delete out; + if (!_save.save(0, _screenshotSize, _varSize + 540, saveFile.destName, buffer, 0)) { + delete[] buffer; return false; } - } - out->finalize(); - if (out->ioFailed()) { - warning("Can't save to slot %d", slot); - delete out; - return false; + delete[] buffer; } - debugC(1, kDebugFileIO, "Saved to slot %d", slot); - delete out; return true; } -void SaveLoad_v3::initBuffer() { - if (_buffer) +void SaveLoad_v3::assertInited() { + if (_varSize > 0) return; - _buffer = new byte*[_stagesCount]; - - assert(_buffer); + _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; - _buffer[0] = new byte[1000]; - _buffer[1] = new byte[1200]; - _buffer[2] = 0; + _save.addStage(500); + _save.addStage(40, false); + _save.addStage(_varSize); +} - assert(_buffer[0] && _buffer[1]); +void SaveLoad_v3::buildScreenshotIndex(byte *buffer, char *name, int n) { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; - memset(_buffer[0], 0, 1000); - memset(_buffer[1], 0, 1200); + memset(buffer, 0, n); + for (int i = 0; i < n; i++) { + in = saveMan->openForLoading(setCurrentSlot(name, i)); + if (in) { + delete in; + buffer[i] = 1; + } + } } } // End of namespace Gob diff --git a/engines/gob/saveload_v4.cpp b/engines/gob/saveload_v4.cpp new file mode 100644 index 0000000000..a6548dd82d --- /dev/null +++ b/engines/gob/saveload_v4.cpp @@ -0,0 +1,439 @@ +/* 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 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/endian.h" + +#include "gob/gob.h" +#include "gob/saveload.h" +#include "gob/game.h" +#include "gob/inter.h" + +namespace Gob { + +SaveLoad_v4::SaveFile SaveLoad_v4::_saveFiles[] = { + { "save.tmp", 0, kSaveModeSave, kSaveScreenProps }, + { "cat.inf", 0, kSaveModeSave, kSaveGame }, + { "save0.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save1.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save2.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save3.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save4.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save5.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save6.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save7.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save8.tmp", 0, kSaveModeSave, kSaveGameScreenProps }, + { "save9.tmp", 0, kSaveModeSave, kSaveGameScreenProps } +}; + +SaveLoad_v4::SaveLoad_v4(GobEngine *vm, const char *targetName) : + SaveLoad(vm, targetName) { + + _firstSizeGame = true; + + _saveFiles[0].destName = 0; + _saveFiles[1].destName = new char[strlen(targetName) + 5]; + _saveFiles[2].destName = _saveFiles[1].destName; + _saveFiles[3].destName = _saveFiles[1].destName; + _saveFiles[4].destName = _saveFiles[1].destName; + _saveFiles[5].destName = _saveFiles[1].destName; + _saveFiles[6].destName = _saveFiles[1].destName; + _saveFiles[7].destName = _saveFiles[1].destName; + _saveFiles[8].destName = _saveFiles[1].destName; + _saveFiles[9].destName = _saveFiles[1].destName; + _saveFiles[10].destName = _saveFiles[1].destName; + _saveFiles[11].destName = _saveFiles[1].destName; + + sprintf(_saveFiles[1].destName, "%s.s00", targetName); + + _varSize = 0; + _hasIndex = false; + memset(_propBuffer, 0, 1000); + + _screenProps = new byte[512000]; + memset(_screenProps, 0, 512000); +} + +SaveLoad_v4::~SaveLoad_v4() { + delete[] _screenProps; + delete[] _saveFiles[1].destName; +} + +SaveLoad::SaveMode SaveLoad_v4::getSaveMode(const char *fileName) { + fileName = stripPath(fileName); + + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return _saveFiles[i].mode; + + return kSaveModeNone; +} + +int SaveLoad_v4::getSaveType(const char *fileName) { + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return i; + + return -1; +} + +int32 SaveLoad_v4::getSizeVersioned(int type) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveScreenProps: + return getSizeScreenProps(_saveFiles[type]); + case kSaveGame: + return getSizeGame(_saveFiles[type]); + case kSaveGameScreenProps: + return getSizeGameScreenProps(_saveFiles[type]); + default: + break; + } + + return -1; +} + +bool SaveLoad_v4::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveScreenProps: + if (loadScreenProps(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading screen properties"); + break; + + case kSaveGame: + if (loadGame(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading from slot %d", getSlot(offset)); + break; + + case kSaveGameScreenProps: + if (loadGameScreenProps(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While loading screen properties from slot %d", getSlot(offset)); + break; + + default: + break; + } + + return false; +} + +bool SaveLoad_v4::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) { + assertInited(); + + switch (_saveFiles[type].type) { + case kSaveScreenProps: + if (saveScreenProps(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving screen properties"); + break; + + case kSaveGame: + if (saveGame(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving to slot %d", getSlot(offset)); + break; + + case kSaveGameScreenProps: + if (saveGameScreenProps(_saveFiles[type], dataVar, size, offset)) + return true; + + warning("While saving screen properties to slot %d", getSlot(offset)); + break; + + default: + break; + } + + return false; +} + +int SaveLoad_v4::getSlot(int32 offset) const { + return ((offset - 1700) / _varSize); +} + +int SaveLoad_v4::getSlotRemainder(int32 offset) const { + return ((offset - 1700) % _varSize); +} + +int32 SaveLoad_v4::getSizeScreenProps(SaveFile &saveFile) { + return 256000; +} + +int32 SaveLoad_v4::getSizeGame(SaveFile &saveFile) { + if (_firstSizeGame) { + _firstSizeGame = false; + return -1; + } + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + int32 size = -1; + + for (int i = 29; i >= 0; i--) { + in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i)); + if (in) { + delete in; + size = (i + 1) * _varSize + 1700; + break; + } + } + + return size; +} + +int32 SaveLoad_v4::getSizeGameScreenProps(SaveFile &saveFile) { + return -1; + + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + + setCurrentSlot(saveFile.destName, saveFile.sourceName[4] - '0'); + in = saveMan->openForLoading(saveFile.destName); + + if (!in) + return -1; + + int32 size = in->size(); + + delete in; + + return size; +} + +bool SaveLoad_v4::loadScreenProps(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + // Using a sprite as a buffer + if (size <= 0) + return true; + + if ((offset < 0) || (size + offset) > 256000) { + warning("Invalid size (%d) or offset (%d)", size, offset); + return false; + } + + debugC(3, kDebugSaveLoad, "Loading screen properties (%d, %d, %d)", + dataVar, size, offset); + + _vm->_inter->_variables->copyFrom(dataVar, + _screenProps + offset, _screenProps + 256000 + offset, size); + + return true; +} + +bool SaveLoad_v4::loadGame(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + if (size == 0) { + dataVar = 0; + size = _varSize; + } + + if (offset < 500) { + debugC(3, kDebugSaveLoad, "Loading global properties"); + + if ((size + offset) > 500) { + warning("Wrong global properties list size (%d, %d)", size, offset); + return false; + } + + _vm->_inter->_variables->copyFrom(dataVar, + _propBuffer + offset, _propBuffer + offset + 500, size); + + } else if (offset == 500) { + debugC(3, kDebugSaveLoad, "Loading save index"); + + if (size != 1200) { + warning("Requested index has wrong size (%d)", size); + return false; + } + + SaveLoad::buildIndex(_vm->_inter->_variables->getAddressOff8(dataVar, 1200), + saveFile.destName, 30, 40, 1000); + + } else { + int slot = getSlot(offset); + int slotRem = getSlotRemainder(offset); + + debugC(2, kDebugSaveLoad, "Loading from slot %d", slot); + + SaveLoad::setCurrentSlot(saveFile.destName, slot); + + if ((slot < 0) || (slot >= 30) || (slotRem != 0)) { + warning("Invalid loading procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, slot, slotRem); + return false; + } + + if (!_save.load(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables)) + return false; + } + + return true; +} + +bool SaveLoad_v4::loadGameScreenProps(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + if (size != -5) { + warning("Invalid loading procedure (%d, %d, %d)", dataVar, size, offset); + return false; + } + + setCurrentSlot(saveFile.destName, saveFile.sourceName[4] - '0'); + + if (!_save.load(0, 256000, _varSize + 540, saveFile.destName, + _screenProps, _screenProps + 256000)) + return false; + + return true; +} + +bool SaveLoad_v4::saveScreenProps(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + // Using a sprite as a buffer + if (size <= 0) + return true; + + if ((offset < 0) || (size + offset) > 256000) { + warning("Invalid size (%d) or offset (%d)", size, offset); + return false; + } + + debugC(3, kDebugSaveLoad, "Saving screen properties (%d, %d, %d)", + dataVar, size, offset); + + _vm->_inter->_variables->copyTo(dataVar, + _screenProps + offset, _screenProps + 256000 + offset, size); + + return true; +} + +bool SaveLoad_v4::saveGame(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + if (size == 0) { + dataVar = 0; + size = _varSize; + } + + if (offset < 500) { + debugC(3, kDebugSaveLoad, "Loading global properties"); + + if ((size + offset) > 500) { + warning("Wrong global properties list size (%d, %d)", size, offset); + return false; + } + + _vm->_inter->_variables->copyTo(dataVar, + _propBuffer + offset, _propBuffer + offset + 500, size); + + } else if (offset == 500) { + debugC(3, kDebugSaveLoad, "Saving save index"); + + if (size != 1200) { + warning("Requested index has wrong size (%d)", size); + return false; + } + + _vm->_inter->_variables->copyTo(dataVar, _indexBuffer, 0, size); + _hasIndex = true; + + } else { + int slot = getSlot(offset); + int slotRem = getSlotRemainder(offset); + + debugC(2, kDebugSaveLoad, "Saving to slot %d", slot); + + SaveLoad::setCurrentSlot(saveFile.destName, slot); + + if ((slot < 0) || (slot >= 30) || (slotRem != 0)) { + warning("Invalid saving procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, slot, slotRem); + return false; + } + + if (!_hasIndex) { + warning("No index written yet"); + return false; + } + + _hasIndex = false; + + if(!_save.save(0, 500, 0, saveFile.destName, _propBuffer, _propBuffer + 500)) + return false; + + if(!_save.save(0, 40, 500, saveFile.destName, _indexBuffer + (slot * 40), 0)) + return false; + + if (!_save.save(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables)) + return false; + + } + + return true; +} + +bool SaveLoad_v4::saveGameScreenProps(SaveFile &saveFile, + int16 dataVar, int32 size, int32 offset) { + + if (size != -5) { + warning("Invalid saving procedure (%d, %d, %d)", dataVar, size, offset); + return false; + } + + setCurrentSlot(saveFile.destName, saveFile.sourceName[4] - '0'); + + if (!_save.save(0, 256000, _varSize + 540, saveFile.destName, + _screenProps, _screenProps + 256000)) + return false; + + return true; +} + +void SaveLoad_v4::assertInited() { + if (_varSize > 0) + return; + + _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + + _save.addStage(500); + _save.addStage(40, false); + _save.addStage(_varSize); + _save.addStage(256000); +} + +} // End of namespace Gob diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index 3f9ec9e6f2..6b52cdbbd6 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" @@ -101,7 +100,6 @@ int16 Scenery::loadStatic(char search) { byte *extData = 0; byte *dataPtr; Static *ptr; - int16 pictDescId; int16 width; int16 height; int16 sprResId; @@ -144,8 +142,6 @@ int16 Scenery::loadStatic(char search) { dataPtr += 2; ptr->layers = new StaticLayer[ptr->layersCount]; - ptr->pieces = new PieceDesc*[picsCount]; - ptr->piecesFromExt = new bool[picsCount]; for (int i = 0; i < ptr->layersCount; i++) { int16 offset = READ_LE_UINT16(dataPtr + i * 2); @@ -155,9 +151,9 @@ int16 Scenery::loadStatic(char search) { ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount]; for (int j = 0; j < ptr->layers[i].planeCount; ++j) { - ptr->layers[i].planes[j].pictIndex = layerData.readSByte(); - ptr->layers[i].planes[j].pieceIndex = layerData.readSByte(); - ptr->layers[i].planes[j].drawOrder = layerData.readSByte(); + ptr->layers[i].planes[j].pictIndex = layerData.readByte(); + ptr->layers[i].planes[j].pieceIndex = layerData.readByte(); + ptr->layers[i].planes[j].drawOrder = layerData.readByte(); ptr->layers[i].planes[j].destX = layerData.readSint16LE(); ptr->layers[i].planes[j].destY = layerData.readSint16LE(); ptr->layers[i].planes[j].transp = layerData.readSByte(); @@ -167,18 +163,13 @@ int16 Scenery::loadStatic(char search) { backsPtr++; } + ptr->pieces = new PieceDesc*[picsCount]; + ptr->piecesCount = new uint32[picsCount]; + for (int i = 0; i < picsCount; i++) { - pictDescId = _vm->_inter->load16(); + int16 pictDescId = _vm->_inter->load16(); - if (pictDescId >= 30000) { - ptr->pieces[i] = - (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0); - ptr->piecesFromExt[i] = true; - } else { - ptr->pieces[i] = - (PieceDesc *) _vm->_game->loadTotResource(pictDescId); - ptr->piecesFromExt[i] = false; - } + loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]); width = _vm->_inter->load16(); height = _vm->_inter->load16(); @@ -225,8 +216,7 @@ void Scenery::freeStatic(int16 index) { return; for (int i = 0; i < _staticPictCount[index]; i++) { - if (_statics[index].piecesFromExt[i]) - delete[] _statics[index].pieces[i]; + delete[] _statics[index].pieces[i]; spr = _staticPictToSprite[index * 7 + i]; _spriteRefs[spr]--; @@ -240,7 +230,7 @@ void Scenery::freeStatic(int16 index) { delete[] _statics[index].layers[i].planes; delete[] _statics[index].layers; delete[] _statics[index].pieces; - delete[] _statics[index].piecesFromExt; + delete[] _statics[index].piecesCount; _statics[index].layersCount = 0; _staticPictCount[index] = -1; @@ -254,8 +244,8 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { int16 order; int16 plane; - int16 pieceIndex; - int16 pictIndex; + uint16 pieceIndex; + uint16 pictIndex; int16 left; int16 right; @@ -278,7 +268,7 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { } planeCount = layerPtr->planeCount; - for (order = 0; order < 40; order++) { + for (order = 0; order < 100; order++) { for (plane = 0, planePtr = layerPtr->planes; plane < planeCount; plane++, planePtr++) { if (planePtr->drawOrder != order) @@ -287,12 +277,21 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { pieceIndex = planePtr->pieceIndex; pictIndex = planePtr->pictIndex - 1; + if (pictIndex >= _staticPictCount[scenery]) + continue; + + if (!ptr->pieces || !ptr->pieces[pictIndex]) + continue; + + if (pieceIndex >= ptr->piecesCount[pictIndex]) + continue; + _vm->_draw->_destSpriteX = planePtr->destX; _vm->_draw->_destSpriteY = planePtr->destY; - left = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].left); - right = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].right); - top = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].top); - bottom = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].bottom); + left = ptr->pieces[pictIndex][pieceIndex].left; + right = ptr->pieces[pictIndex][pieceIndex].right; + top = ptr->pieces[pictIndex][pieceIndex].top; + bottom = ptr->pieces[pictIndex][pieceIndex].bottom; _vm->_draw->_sourceSurface = _staticPictToSprite[scenery * 7 + pictIndex]; @@ -314,8 +313,8 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { int16 planeCount; int16 order; int16 plane; - int16 pieceIndex; - int16 pictIndex; + uint16 pieceIndex; + uint16 pictIndex; int16 left; int16 right; @@ -330,7 +329,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { planeCount = layerPtr->planeCount; - for (order = orderFrom; order < 40; order++) { + for (order = orderFrom; order < 100; order++) { for (planePtr = layerPtr->planes, plane = 0; plane < planeCount; plane++, planePtr++) { if (planePtr->drawOrder != order) @@ -338,13 +337,23 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { pieceIndex = planePtr->pieceIndex; pictIndex = planePtr->pictIndex - 1; + + if (pictIndex >= _staticPictCount[index]) + continue; + + if (!pictPtr || !pictPtr[pictIndex]) + continue; + + if (pieceIndex >= _statics[index].piecesCount[pictIndex]) + continue; + _vm->_draw->_destSpriteX = planePtr->destX; _vm->_draw->_destSpriteY = planePtr->destY; - left = FROM_LE_16(pictPtr[pictIndex][pieceIndex].left); - right = FROM_LE_16(pictPtr[pictIndex][pieceIndex].right); - top = FROM_LE_16(pictPtr[pictIndex][pieceIndex].top); - bottom = FROM_LE_16(pictPtr[pictIndex][pieceIndex].bottom); + left = pictPtr[pictIndex][pieceIndex].left; + right = pictPtr[pictIndex][pieceIndex].right; + top = pictPtr[pictIndex][pieceIndex].top; + bottom = pictPtr[pictIndex][pieceIndex].bottom; if (_vm->_draw->_destSpriteX > _toRedrawRight) continue; @@ -415,7 +424,6 @@ int16 Scenery::loadAnim(char search) { byte *extData; byte *dataPtr; Animation *ptr; - int16 pictDescId; int16 width; int16 height; int16 sprResId; @@ -454,9 +462,6 @@ int16 Scenery::loadAnim(char search) { dataPtr += 2; ptr->layers = new AnimLayer[ptr->layersCount]; - ptr->pieces = new PieceDesc*[picsCount]; - ptr->piecesFromExt = new bool[picsCount]; - ptr->sizes = new uint16[picsCount]; for (i = 0; i < ptr->layersCount; i++) { int16 offset = READ_LE_UINT16(dataPtr + i * 2); @@ -492,23 +497,13 @@ int16 Scenery::loadAnim(char search) { } } + ptr->pieces = new PieceDesc*[picsCount]; + ptr->piecesCount = new uint32[picsCount]; + for (i = 0; i < picsCount; i++) { - pictDescId = _vm->_inter->load16(); - if (pictDescId >= 30000) { - uint32 size; - - ptr->pieces[i] = - (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0, &size); - ptr->piecesFromExt[i] = true; - ptr->sizes[i] = size / 8; - } else { - int16 size; + int16 pictDescId = _vm->_inter->load16(); - ptr->pieces[i] = - (PieceDesc *) _vm->_game->loadTotResource(pictDescId, &size); - ptr->piecesFromExt[i] = false; - ptr->sizes[i] = size / 8; - } + loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]); width = _vm->_inter->load16(); height = _vm->_inter->load16(); @@ -554,8 +549,7 @@ void Scenery::freeAnim(int16 index) { return; for (int i = 0; i < _animPictCount[index]; i++) { - if (_animations[index].piecesFromExt[i]) - delete[] _animations[index].pieces[i]; + delete[] _animations[index].pieces[i]; spr = _animPictToSprite[index * 7 + i]; _spriteRefs[spr]--; @@ -569,8 +563,7 @@ void Scenery::freeAnim(int16 index) { delete[] _animations[index].layers[i].frames; delete[] _animations[index].layers; delete[] _animations[index].pieces; - delete[] _animations[index].piecesFromExt; - delete[] _animations[index].sizes; + delete[] _animations[index].piecesCount; _animPictCount[index] = 0; } @@ -620,8 +613,8 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1]; - if (!_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) { - _toRedrawLeft = -1234; + if ((obj.videoSlot == 0) || !_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) { + _toRedrawLeft = -12345; return; } @@ -629,8 +622,17 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, frame = _vm->_vidPlayer->getFramesCount(obj.videoSlot - 1) - 1; // Seek to frame - while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame) - _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); + if (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < 256) { + while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame) + _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); + } else { + int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1); + uint8 frameWrap = curFrame / 256; + frame = (frame + 1) % 256; + + while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < (frameWrap * 256 + frame)) + _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); + } destX = 0; destY = 0; @@ -724,7 +726,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, } - if (flags & 4) { + if (!(flags & 4)) { _animLeft = _toRedrawLeft = left; _animTop = _toRedrawTop = top; _animRight = _toRedrawRight = right; @@ -812,20 +814,19 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, pictIndex = (pictIndex & 15) - 1; - if ((pictIndex == 0xFFFF) || (_animPictCount[animation] <= pictIndex)) { - warning("Scenery::updateAnim: pictIndex out of range"); - return; - } + if (pictIndex >= _animPictCount[animation]) + continue; - if (_animations[animation].sizes[pictIndex] <= pieceIndex) { - warning("Scenery::updateAnim: pieceIndex out of range"); + if (!pictPtr[pictIndex]) continue; - } - left = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].left); - right = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].right); - top = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].top); - bottom = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].bottom); + if (pieceIndex >= _animations[animation].piecesCount[pictIndex]) + continue; + + left = pictPtr[pictIndex][pieceIndex].left; + right = pictPtr[pictIndex][pieceIndex].right; + top = pictPtr[pictIndex][pieceIndex].top; + bottom = pictPtr[pictIndex][pieceIndex].bottom; if (flags & 2) { if (destX < _vm->_mult->_animLeft) { @@ -946,4 +947,42 @@ Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) { return &_animations[index].layers[layer]; } +void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) { + byte *data; + uint32 size; + bool fromExt = false; + + if (pictDescId >= 30000) { + fromExt = true; + + uint32 eSize; + + data = _vm->_game->loadExtData(pictDescId, 0, 0, &eSize); + size = eSize; + } else { + int16 tSize; + + data = _vm->_game->loadTotResource(pictDescId, &tSize); + size = tSize; + } + + if (!data) + error("Scenery::loadPieces(): Can't load pictDescId %d", pictDescId); + + piecesCount = size / 8; + pieceDesc = new PieceDesc[piecesCount]; + + Common::MemoryReadStream pieceData(data, size); + + for (uint32 i = 0; i < piecesCount; i++) { + pieceDesc[i].left = (int16) pieceData.readUint16LE(); + pieceDesc[i].right = (int16) pieceData.readUint16LE(); + pieceDesc[i].top = (int16) pieceData.readUint16LE(); + pieceDesc[i].bottom = (int16) pieceData.readUint16LE(); + } + + if (fromExt) + delete[] data; +} + } // End of namespace Gob diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h index a1a1304d4d..21bf29deda 100644 --- a/engines/gob/scenery.h +++ b/engines/gob/scenery.h @@ -34,16 +34,16 @@ public: #include "common/pack-start.h" // START STRUCT PACKING struct PieceDesc { - int16 left; //NOTE: - int16 right; //These are stored in Little Endian format - int16 top; //And should be converted by client code when accessed - int16 bottom; //i.e. use FROM_LE_16() + int16 left; + int16 right; + int16 top; + int16 bottom; } PACKED_STRUCT; struct StaticPlane { - int8 pictIndex; - int8 pieceIndex; - int8 drawOrder; + uint8 pictIndex; + uint8 pieceIndex; + uint8 drawOrder; int16 destX; int16 destY; int8 transp; @@ -82,19 +82,16 @@ public: int16 layersCount; StaticLayer *layers; PieceDesc **pieces; - bool *piecesFromExt; - Static() : layersCount(0), layers(0), pieces(0), - piecesFromExt(0) {} + uint32 *piecesCount; + Static() : layersCount(0), layers(0), pieces(0), piecesCount(0) {} }; struct Animation { int16 layersCount; AnimLayer *layers; PieceDesc **pieces; - bool *piecesFromExt; - uint16 *sizes; - Animation() : layersCount(0), layers(0), pieces(0), - piecesFromExt(0) {} + uint32 *piecesCount; + Animation() : layersCount(0), layers(0), pieces(0), piecesCount(0) {} }; int16 _curStatic; @@ -151,6 +148,8 @@ protected: GobEngine *_vm; + void loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount); + void updateStatic(int16 orderFrom, byte index, byte layer); }; diff --git a/engines/gob/scenery_v1.cpp b/engines/gob/scenery_v1.cpp index 5d3eb15a95..605b098693 100644 --- a/engines/gob/scenery_v1.cpp +++ b/engines/gob/scenery_v1.cpp @@ -23,13 +23,12 @@ * */ - #include "common/endian.h" #include "gob/gob.h" #include "gob/scenery.h" #include "gob/util.h" -#include "gob/cdrom.h" +#include "gob/sound/sound.h" namespace Gob { @@ -37,11 +36,11 @@ Scenery_v1::Scenery_v1(GobEngine *vm) : Scenery(vm) { } int16 Scenery_v1::loadAnim(char search) { - if (_vm->_cdrom->_cdPlaying) { - while (_vm->_cdrom->getTrackPos() != -1) + if (_vm->_sound->cdIsPlaying()) { + while (_vm->_sound->cdGetTrackPos() != -1) _vm->_util->longDelay(50); - _vm->_cdrom->_cdPlaying = false; + _vm->_sound->cdStop(); } return Scenery::loadAnim(search); diff --git a/engines/gob/scenery_v2.cpp b/engines/gob/scenery_v2.cpp index 6ed377af64..1a0de6f291 100644 --- a/engines/gob/scenery_v2.cpp +++ b/engines/gob/scenery_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp deleted file mode 100644 index 6b227cfb0e..0000000000 --- a/engines/gob/sound.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* 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 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/endian.h" - -#include "gob/gob.h" -#include "gob/sound.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/game.h" - -namespace Gob { - -void SoundDesc::set(SoundType type, SoundSource src, - byte *data, uint32 dSize) { - - free(); - - _type = type; - _source = src; - _data = _dataPtr = data; - _size = dSize; -} - -void SoundDesc::load(SoundType type, SoundSource src, - byte *data, uint32 dSize) { - - free(); - - _source = src; - switch (type) { - case SOUND_ADL: - loadADL(data, dSize); - break; - case SOUND_SND: - loadSND(data, dSize); - break; - } -} - -void SoundDesc::free() { - if (_source != SOUND_TOT) - delete[] _data; - _data = _dataPtr = 0; - _id = 0; -} - -void SoundDesc::convToSigned() { - if ((_type == SOUND_SND) && _data && _dataPtr) - for (uint32 i = 0; i < _size; i++) - _dataPtr[i] ^= 0x80; -} - -void SoundDesc::loadSND(byte *data, uint32 dSize) { - assert(dSize > 6); - - _type = SOUND_SND; - _data = data; - _dataPtr = data + 6; - _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700); - _flag = data[0] ? (data[0] & 0x7F) : 8; - data[0] = 0; - _size = MIN(READ_BE_UINT32(data), dSize - 6); -} - -void SoundDesc::loadADL(byte *data, uint32 dSize) { - _type = SOUND_ADL; - _data = _dataPtr = data; - _size = dSize; -} - -Snd::Snd(GobEngine *vm) : _vm(vm) { - _playingSound = 0; - _curSoundDesc = 0; - - _rate = _vm->_mixer->getOutputRate(); - _end = true; - _data = 0; - _length = 0; - _freq = 0; - _repCount = 0; - - _offset = 0; - _offsetFrac = 0; - _offsetInc = 0; - - _cur = 0; - _last = 0; - - _fade = false; - _fadeVol = 65536; - _fadeVolStep = 0; - _fadeSamples = 0; - _curFadeSamples = 0; - - _compositionSamples = 0; - _compositionSampleCount = 0; - _compositionPos = -1; - - _speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate()); - - _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, - this, -1, 255, 0, false, true); - _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_speakerHandle, - _speakerStream, -1, 50, 0, false, true); -} - -Snd::~Snd() { - // stop permanent streams manually: - - // First the speaker stream - _vm->_mixer->stopHandle(_speakerHandle); - delete _speakerStream; - - // Next, this stream (class Snd is an AudioStream, too) - _vm->_mixer->stopHandle(_handle); -} - -void Snd::speakerOn(int16 frequency, int32 length) { - _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length); -} - -void Snd::speakerOff() { - _speakerStream->stop(); -} - -void Snd::speakerOnUpdate(uint32 milis) { - if (_speakerStream->isPlaying()) - _speakerStream->stop(milis); -} - -void Snd::stopSound(int16 fadeLength, SoundDesc *sndDesc) { - Common::StackLock slock(_mutex); - - if (sndDesc && (sndDesc != _curSoundDesc)) - return; - - if (fadeLength <= 0) { - _data = 0; - _end = true; - _playingSound = 0; - _curSoundDesc = 0; - return; - } - - _fade = true; - _fadeVol = 65536; - _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); - _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples)); - _curFadeSamples = 0; -} - -void Snd::setRepeating(int32 repCount) { - Common::StackLock slock(_mutex); - - _repCount = repCount; -} - -void Snd::waitEndPlay(bool interruptible, bool stopComp) { - if (stopComp) - _compositionPos = -1; - while (!_end && !_vm->_quitRequested) { - if (interruptible && (_vm->_util->checkKey() == 0x11B)) { - WRITE_VAR(57, -1); - return; - } - _vm->_util->longDelay(200); - } - stopSound(0); -} - -void Snd::stopComposition() { - if (_compositionPos != -1) { - stopSound(0); - _compositionPos = -1; - } -} - -void Snd::nextCompositionPos() { - int8 slot; - - while ((++_compositionPos < 50) && - ((slot = _composition[_compositionPos]) != -1)) { - if ((slot >= 0) && (slot < _compositionSampleCount)) { - SoundDesc &sample = _compositionSamples[slot]; - if (!sample.empty() && (sample.getType() == SOUND_SND)) { - setSample(sample, 1, 0, 0); - return; - } - } - if (_compositionPos == 49) - _compositionPos = -1; - } - _compositionPos = -1; -} - -void Snd::playComposition(int16 *composition, int16 freqVal, - SoundDesc *sndDescs, int8 sndCount) { - int i; - - waitEndPlay(); - stopComposition(); - - _compositionSamples = sndDescs ? sndDescs : _vm->_game->_soundSamples; - _compositionSampleCount = sndCount; - - i = -1; - do { - i++; - _composition[i] = composition[i]; - } while ((i < 50) && (composition[i] != -1)); - - _compositionPos = -1; - nextCompositionPos(); -} - -void Snd::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, - int16 fadeLength) { - - if (frequency <= 0) - frequency = sndDesc._frequency; - - _curSoundDesc = &sndDesc; - sndDesc._repCount = repCount - 1; - sndDesc._frequency = frequency; - - _data = (int8 *) sndDesc.getData(); - _length = sndDesc.size(); - _freq = frequency; - - _repCount = repCount; - _end = false; - _playingSound = 1; - - _offset = 0; - _offsetFrac = 0; - _offsetInc = (_freq << FRAC_BITS) / _rate; - - _last = _cur; - _cur = _data[0]; - - _curFadeSamples = 0; - if (fadeLength == 0) { - _fade = false; - _fadeVol = 65536; - _fadeSamples = 0; - _fadeVolStep = 0; - } else { - _fade = true; - _fadeVol = 0; - _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); - _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples)); - } -} - -bool Snd::loadSample(SoundDesc &sndDesc, const char *fileName) { - byte *data; - uint32 size; - - data = (byte *) _vm->_dataIO->getData(fileName); - if (!data) - return false; - - size = _vm->_dataIO->getDataSize(fileName); - sndDesc.load(SOUND_SND, SOUND_FILE, data, size); - - return true; -} - -void Snd::freeSample(SoundDesc &sndDesc) { - stopSound(0, &sndDesc); - sndDesc.free(); -} - -void Snd::playSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, - int16 fadeLength) { - Common::StackLock slock(_mutex); - - if (!_end) - return; - - setSample(sndDesc, repCount, frequency, fadeLength); -} - -void Snd::checkEndSample() { - if (_compositionPos != -1) - nextCompositionPos(); - else if ((_repCount == -1) || (--_repCount > 0)) { - _offset = 0; - _offsetFrac = 0; - _end = false; - _playingSound = 1; - } else { - _end = true; - _playingSound = 0; - } -} - -int Snd::readBuffer(int16 *buffer, const int numSamples) { - Common::StackLock slock(_mutex); - - for (int i = 0; i < numSamples; i++) { - if (!_data) - return i; - if (_end || (_offset >= _length)) - checkEndSample(); - if (_end) - return i; - - // Linear interpolation. See sound/rate.cpp - - int16 val = (_last + (((_cur - _last) * _offsetFrac + - FRAC_HALF) >> FRAC_BITS)) << 8; - *buffer++ = (val * _fadeVol) >> 16; - - _offsetFrac += _offsetInc; - - // Was there an integral change? - if (fracToInt(_offsetFrac) > 0) { - _last = _cur; - _cur = _data[_offset]; - _offset += fracToInt(_offsetFrac); - _offsetFrac &= FRAC_LO_MASK; - } - - if (_fade) { - - if (++_curFadeSamples >= _fadeSamples) { - if (_fadeVolStep > 0) { - _data = 0; - _end = true; - _playingSound = 0; - _compositionPos = -1; - _curSoundDesc = 0; - } else { - _fadeVol = 65536; - _fade = false; - } - } else - _fadeVol -= _fadeVolStep; - - if (_fadeVol < 0) - _fadeVol = 0; - - } - } - return numSamples; -} - -} // End of namespace Gob diff --git a/engines/gob/sound.h b/engines/gob/sound.h deleted file mode 100644 index 6780c201b5..0000000000 --- a/engines/gob/sound.h +++ /dev/null @@ -1,172 +0,0 @@ -/* 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 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$ - * - */ - -#ifndef GOB_SOUND_H -#define GOB_SOUND_H - -#include "common/mutex.h" -#include "common/frac.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" -#include "sound/softsynth/pcspk.h" - -namespace Gob { - -enum SoundType { - SOUND_SND, - SOUND_ADL -}; - -enum SoundSource { - SOUND_FILE, - SOUND_TOT, - SOUND_EXT -}; - -class SoundDesc { -public: - int16 _repCount; - int16 _frequency; - int16 _flag; - int16 _id; - - byte *getData() { return _dataPtr; } - uint32 size() { return _size; } - bool empty() { return !_dataPtr; } - bool isId(int16 id) { return _dataPtr && _id == id; } - SoundType getType() { return _type; } - - void set(SoundType type, SoundSource src, byte *data, uint32 dSize); - void load(SoundType type, SoundSource src, byte *data, uint32 dSize); - void free(); - void convToSigned(); - - // Which fade out length to use when the fade starts half-way through? - int16 calcFadeOutLength(int16 frequency) { - return (10 * (_size / 2)) / frequency; - } - uint32 calcLength(int16 repCount, int16 frequency, bool fade) { - uint32 fadeSize = fade ? _size / 2 : 0; - return ((_size * repCount - fadeSize) * 1000) / frequency; - } - - SoundDesc() : _data(0), _dataPtr(0), _size(0), _type(SOUND_SND), - _source(SOUND_FILE), _repCount(0), _frequency(0), - _flag(0), _id(0) {} - ~SoundDesc() { free(); } - -private: - byte *_data; - byte *_dataPtr; - uint32 _size; - - SoundType _type; - SoundSource _source; - - void loadSND(byte *data, uint32 dSize); - void loadADL(byte *data, uint32 dSize); -}; - -class Snd : public Audio::AudioStream { -public: - char _playingSound; - - Snd(GobEngine *vm); - ~Snd(); - - void speakerOn(int16 frequency, int32 length); - void speakerOff(); - void speakerOnUpdate(uint32 milis); - void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0); - - bool loadSample(SoundDesc &sndDesc, const char *fileName); - void freeSample(SoundDesc &sndDesc); - void playSample(SoundDesc &sndDesc, int16 repCount, - int16 frequency, int16 fadeLength = 0); - - void playComposition(int16 *composition, int16 freqVal, - SoundDesc *sndDescs = 0, int8 sndCount = 60); - void stopComposition(); - void setRepeating(int32 repCount); - void waitEndPlay(bool interruptible = false, bool stopComp = true); - - static void convToSigned(byte *buffer, int length) { - while (length-- > 0) - *buffer++ ^= 0x80; - } - - int readBuffer(int16 *buffer, const int numSamples); - bool isStereo() const { return false; } - bool endOfData() const { return _end; } - bool endOfStream() const { return false; } - int getRate() const { return _rate; } - -protected: - Audio::PCSpeaker *_speakerStream; - Audio::SoundHandle _speakerHandle; - - Audio::SoundHandle *_activeHandle; - Audio::SoundHandle _compositionHandle; - - SoundDesc *_compositionSamples; - int8 _compositionSampleCount; - int16 _composition[50]; - int8 _compositionPos; - - Audio::SoundHandle _handle; - Common::Mutex _mutex; - SoundDesc *_curSoundDesc; - bool _end; - int8 *_data; - uint32 _length; - uint32 _rate; - int32 _freq; - int32 _repCount; - - uint32 _offset; - frac_t _offsetFrac; - frac_t _offsetInc; - - int16 _cur; - int16 _last; - - bool _fade; - int32 _fadeVol; - int32 _fadeVolStep; - uint8 _fadeLength; - uint32 _fadeSamples; - uint32 _curFadeSamples; - - GobEngine *_vm; - - void setSample(SoundDesc &sndDesc, int16 repCount, - int16 frequency, int16 fadeLength); - void checkEndSample(); - void nextCompositionPos(); -}; - -} // End of namespace Gob - -#endif // GOB_SOUND_H diff --git a/engines/gob/music.cpp b/engines/gob/sound/adlib.cpp index 7be046c02a..b3d392ad1e 100644 --- a/engines/gob/music.cpp +++ b/engines/gob/sound/adlib.cpp @@ -24,91 +24,55 @@ */ #include "common/file.h" - #include "common/endian.h" #include "gob/gob.h" -#include "gob/music.h" -#include "gob/game.h" -#include "gob/util.h" +#include "gob/sound/adlib.h" namespace Gob { -const char *Adlib::_tracks[][2] = { - {"avt00.tot", "mine"}, - {"avt001.tot", "nuit"}, - {"avt002.tot", "campagne"}, - {"avt003.tot", "extsor1"}, - {"avt004.tot", "interieure"}, - {"avt005.tot", "zombie"}, - {"avt006.tot", "zombie"}, - {"avt007.tot", "campagne"}, - {"avt008.tot", "campagne"}, - {"avt009.tot", "extsor1"}, - {"avt010.tot", "extsor1"}, - {"avt011.tot", "interieure"}, - {"avt012.tot", "zombie"}, - {"avt014.tot", "nuit"}, - {"avt015.tot", "interieure"}, - {"avt016.tot", "statue"}, - {"avt017.tot", "zombie"}, - {"avt018.tot", "statue"}, - {"avt019.tot", "mine"}, - {"avt020.tot", "statue"}, - {"avt021.tot", "mine"}, - {"avt022.tot", "zombie"} -}; - -const char *Adlib::_trackFiles[] = { -// "musmac1.adl", // TODO: This track isn't played correctly at all yet - "musmac2.adl", - "musmac3.adl", - "musmac4.adl", - "musmac5.adl", - "musmac6.adl" -}; - -const unsigned char Adlib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18}; -const unsigned char Adlib::_volRegNums[] = { +const unsigned char AdLib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18}; +const unsigned char AdLib::_volRegNums[] = { 3, 4, 5, 11, 12, 13, 19, 20, 21 }; -Adlib::Adlib(GobEngine *vm) : _vm(vm) { - int i; - +AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) { _index = -1; _data = 0; _playPos = 0; _dataSize = 0; - _rate = _vm->_mixer->getOutputRate(); + + _rate = _mixer->getOutputRate(); _opl = makeAdlibOPL(_rate); + _first = true; _ended = false; _playing = false; _needFree = false; + _repCount = -1; _samplesTillPoll = 0; - for (i = 0; i < 16; i ++) + for (int i = 0; i < 16; i ++) _pollNotes[i] = 0; setFreqs(); - _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle, + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle, this, -1, 255, 0, false, true); } -Adlib::~Adlib() { +AdLib::~AdLib() { Common::StackLock slock(_mutex); - _vm->_mixer->stopHandle(_handle); + _mixer->stopHandle(_handle); OPLDestroy(_opl); if (_data && _needFree) delete[] _data; } -int Adlib::readBuffer(int16 *buffer, const int numSamples) { +int AdLib::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock slock(_mutex); int samples; int render; @@ -160,12 +124,12 @@ int Adlib::readBuffer(int16 *buffer, const int numSamples) { return numSamples; } -void Adlib::writeOPL(byte reg, byte val) { - debugC(6, kDebugMusic, "writeOPL(%02X, %02X)", reg, val); +void AdLib::writeOPL(byte reg, byte val) { + debugC(6, kDebugSound, "writeOPL(%02X, %02X)", reg, val); OPLWriteReg(_opl, reg, val); } -void Adlib::setFreqs() { +void AdLib::setFreqs() { byte lin; byte col; long val = 0; @@ -191,7 +155,7 @@ void Adlib::setFreqs() { } } -void Adlib::reset() { +void AdLib::reset() { _first = true; OPLResetChip(_opl); _samplesTillPoll = 0; @@ -209,13 +173,13 @@ void Adlib::reset() { writeOPL(0x01, 0x20); } -void Adlib::setVoices() { +void AdLib::setVoices() { // Definitions of the 9 instruments for (int i = 0; i < 9; i++) setVoice(i, i, true); } -void Adlib::setVoice(byte voice, byte instr, bool set) { +void AdLib::setVoice(byte voice, byte instr, bool set) { int i; int j; uint16 strct[27]; @@ -251,7 +215,7 @@ void Adlib::setVoice(byte voice, byte instr, bool set) { } } -void Adlib::setKey(byte voice, byte note, bool on, bool spec) { +void AdLib::setKey(byte voice, byte note, bool on, bool spec) { short freq = 0; short octa = 0; @@ -317,12 +281,12 @@ void Adlib::setKey(byte voice, byte note, bool on, bool spec) { warning("Voice %d, note %02X unknown\n", voice, note); } -void Adlib::setVolume(byte voice, byte volume) { +void AdLib::setVolume(byte voice, byte volume) { volume = 0x3F - (volume * 0x7E + 0x7F) / 0xFE; writeOPL(0x40 + _volRegNums[voice], volume); } -void Adlib::pollMusic() { +void AdLib::pollMusic() { unsigned char instr; byte channel; byte note; @@ -419,24 +383,7 @@ void Adlib::pollMusic() { _samplesTillPoll = tempo * (_rate / 1000); } -void Adlib::playBgMusic() { - for (int i = 0; i < ARRAYSIZE(_tracks); i++) - if (!scumm_stricmp(_vm->_game->_curTotFile, _tracks[i][0])) { - playTrack(_tracks[i][1]); - break; - } -} - -void Adlib::playTrack(const char *trackname) { - if (_playing) return; - - debugC(1, kDebugMusic, "Adlib::playTrack(%s)", trackname); - unload(); - load(_trackFiles[_vm->_util->getRandom(ARRAYSIZE(_trackFiles))]); - startPlay(); -} - -bool Adlib::load(const char *fileName) { +bool AdLib::load(const char *fileName) { Common::File song; unload(); @@ -457,7 +404,7 @@ bool Adlib::load(const char *fileName) { return true; } -void Adlib::load(byte *data, uint32 size, int index) { +bool AdLib::load(byte *data, uint32 size, int index) { unload(); _repCount = 0; @@ -468,9 +415,11 @@ void Adlib::load(byte *data, uint32 size, int index) { reset(); setVoices(); _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; } -void Adlib::unload() { +void AdLib::unload() { _playing = false; _index = -1; @@ -480,4 +429,29 @@ void Adlib::unload() { _needFree = false; } +bool AdLib::isPlaying() const { + return _playing; +} + +bool AdLib::getRepeating() const { + return _repCount != 0; +} + +void AdLib::setRepeating(int32 repCount) { + _repCount = repCount; +} + +int AdLib::getIndex() const { + return _index; +} + +void AdLib::startPlay() { + if (_data) _playing = true; +} + +void AdLib::stopPlay() { + Common::StackLock slock(_mutex); + _playing = false; +} + } // End of namespace Gob diff --git a/engines/gob/music.h b/engines/gob/sound/adlib.h index 199ea515b0..4cd83d5883 100644 --- a/engines/gob/music.h +++ b/engines/gob/sound/adlib.h @@ -23,8 +23,8 @@ * */ -#ifndef GOB_MUSIC_H -#define GOB_MUSIC_H +#ifndef GOB_SOUND_ADLIB_H +#define GOB_SOUND_ADLIB_H #include "common/mutex.h" #include "sound/audiostream.h" @@ -35,61 +35,63 @@ namespace Gob { class GobEngine; -class Adlib : public Audio::AudioStream { +class AdLib : public Audio::AudioStream { public: - Adlib(GobEngine *vm); - ~Adlib(); - - void lock() { _mutex.lock(); } - void unlock() { _mutex.unlock(); } - bool playing() const { return _playing; } - bool getRepeating() const { return _repCount != 0; } - void setRepeating (int32 repCount) { _repCount = repCount; } - int getIndex() const { return _index; } - void startPlay() { if (_data) _playing = true; } - void stopPlay() { - Common::StackLock slock(_mutex); - _playing = false; - } - void playTrack(const char *trackname); - void playBgMusic(); + AdLib(Audio::Mixer &mixer); + ~AdLib(); + + bool isPlaying() const; + int getIndex() const; + bool getRepeating() const; + + void setRepeating(int32 repCount); + + void startPlay(); + void stopPlay(); + bool load(const char *fileName); - void load(byte *data, uint32 size, int index = -1); + bool load(byte *data, uint32 size, int index = -1); void unload(); // AudioStream API - int readBuffer(int16 *buffer, const int numSamples); - bool isStereo() const { return false; } - bool endOfData() const { return !_playing; } - bool endOfStream() const { return false; } - int getRate() const { return _rate; } + int readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return false; } + bool endOfData() const { return !_playing; } + bool endOfStream() const { return false; } + int getRate() const { return _rate; } protected: - static const char *_tracks[][2]; - static const char *_trackFiles[]; static const unsigned char _operators[]; static const unsigned char _volRegNums []; + + Audio::Mixer *_mixer; Audio::SoundHandle _handle; FM_OPL *_opl; - int _index; + + Common::Mutex _mutex; + + uint32 _rate; + byte *_data; byte *_playPos; uint32 _dataSize; - uint32 _rate; + short _freqs[25][12]; byte _notes[11]; byte _notCol[11]; byte _notLin[11]; bool _notOn[11]; byte _pollNotes[16]; + int _samplesTillPoll; int32 _repCount; + bool _playing; bool _first; bool _ended; bool _needFree; - Common::Mutex _mutex; - GobEngine *_vm; + + int _index; void writeOPL(byte reg, byte val); void setFreqs(); @@ -103,4 +105,4 @@ protected: } // End of namespace Gob -#endif // GOB_MUSIC_H +#endif // GOB_SOUND_ADLIB_H diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp new file mode 100644 index 0000000000..f5a7fe0fdb --- /dev/null +++ b/engines/gob/sound/bgatmosphere.cpp @@ -0,0 +1,128 @@ +/* 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 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/system.h" +#include "common/events.h" + +#include "gob/sound/bgatmosphere.h" + +namespace Gob { + +BackgroundAtmosphere::BackgroundAtmosphere(Audio::Mixer &mixer) : + SoundMixer(mixer, Audio::Mixer::kMusicSoundType) { + + _playMode = kPlayModeLinear; + _queuePos = -1; + _shaded = false; + + g_system->getEventManager()->registerRandomSource(_rnd, "gobBA"); +} + +BackgroundAtmosphere::~BackgroundAtmosphere() { + queueClear(); +} + +void BackgroundAtmosphere::play() { + Common::StackLock slock(_mutex); + + _queuePos = -1; + getNextQueuePos(); + + if (_queuePos == -1) + return; + + SoundMixer::play(*_queue[_queuePos], 1, 0); +} + +void BackgroundAtmosphere::stop() { + SoundMixer::stop(0); +} + +void BackgroundAtmosphere::setPlayMode(PlayMode mode) { + _playMode = mode; +} + +void BackgroundAtmosphere::queueSample(SoundDesc &sndDesc) { + Common::StackLock slock(_mutex); + + _queue.push_back(&sndDesc); +} + +void BackgroundAtmosphere::queueClear() { + Common::StackLock slock(_mutex); + + SoundMixer::stop(0); + for (uint i = 0; i < _queue.size(); i++) + delete _queue[i]; + + _queue.clear(); + _queuePos = -1; +} + +void BackgroundAtmosphere::checkEndSample() { + Common::StackLock slock(_mutex); + + getNextQueuePos(); + + if (_queuePos == -1) { + _end = true; + _playingSound = 0; + } else { + SoundMixer::setSample(*_queue[_queuePos], 1, 0, 0); + if (_shaded) + _fadeVol = 20000; + } +} + +void BackgroundAtmosphere::getNextQueuePos() { + if (_queue.size() == 0) { + _queuePos = -1; + return; + } + + switch (_playMode) { + + case kPlayModeLinear: + _queuePos = (_queuePos + 1) % _queue.size(); + break; + + case kPlayModeRandom: + _queuePos = _rnd.getRandomNumber(_queue.size() - 1); + break; + + } +} + +void BackgroundAtmosphere::shade() { + _shaded = true; + _fadeVol = 32768; +} + +void BackgroundAtmosphere::unshade() { + _shaded = false; + _fadeVol = 65536; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h new file mode 100644 index 0000000000..72b5614282 --- /dev/null +++ b/engines/gob/sound/bgatmosphere.h @@ -0,0 +1,75 @@ +/* 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 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$ + * + */ + +#ifndef GOB_SOUND_BGATMOSPHERE_H +#define GOB_SOUND_BGATMOSPHERE_H + +#include "sound/mixer.h" +#include "common/mutex.h" + +#include "gob/sound/sounddesc.h" +#include "gob/sound/soundmixer.h" + +namespace Gob { + +class BackgroundAtmosphere : private SoundMixer { +public: + enum PlayMode { + kPlayModeLinear, + kPlayModeRandom + }; + + BackgroundAtmosphere(Audio::Mixer &mixer); + ~BackgroundAtmosphere(); + + void play(); + void stop(); + + void setPlayMode(PlayMode mode); + + void queueSample(SoundDesc &sndDesc); + void queueClear(); + + void shade(); + void unshade(); + +private: + PlayMode _playMode; + + Common::Array<SoundDesc *> _queue; + int _queuePos; + bool _shaded; + + Common::Mutex _mutex; + + Common::RandomSource _rnd; + + void checkEndSample(); + void getNextQueuePos(); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_BGATMOSPHERE_H diff --git a/engines/gob/cdrom.cpp b/engines/gob/sound/cdrom.cpp index c037d24bbe..eef8025cc2 100644 --- a/engines/gob/cdrom.cpp +++ b/engines/gob/sound/cdrom.cpp @@ -23,20 +23,16 @@ * */ - #include "common/endian.h" +#include "common/util.h" #include "sound/audiocd.h" #include "gob/gob.h" -#include "gob/cdrom.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/game.h" +#include "gob/sound/cdrom.h" namespace Gob { -CDROM::CDROM(GobEngine *vm) : _vm(vm) { +CDROM::CDROM() { _cdPlaying = false; _LICbuffer = 0; @@ -47,116 +43,46 @@ CDROM::CDROM(GobEngine *vm) : _vm(vm) { _startTime = 0; } -void CDROM::readLIC(const char *fname) { - char tmp[80]; - int handle; - uint16 version, startChunk, pos; +CDROM::~CDROM() { +} - freeLICbuffer(); +void CDROM::readLIC(DataStream &stream) { + uint16 version, startChunk, pos; + freeLICBuffer(); *_curTrack = 0; - strncpy0(tmp, fname, 79); - - handle = _vm->_dataIO->openData(tmp); - - if (handle == -1) - return; - - _vm->_dataIO->closeData(handle); - - _vm->_dataIO->getUnpackedData(tmp); - - handle = _vm->_dataIO->openData(tmp); - DataStream *stream = _vm->_dataIO->openAsStream(handle, true); - - version = stream->readUint16LE(); - startChunk = stream->readUint16LE(); - _numTracks = stream->readUint16LE(); + version = stream.readUint16LE(); + startChunk = stream.readUint16LE(); + _numTracks = stream.readUint16LE(); if (version != 3) - error("%s: Unknown version %d", fname, version); + error("Unknown version %d while reading LIC", version); - stream->seek(50); + stream.seek(50); for (int i = 0; i < startChunk; i++) { - pos = stream->readUint16LE(); + pos = stream.readUint16LE(); if (!pos) break; - stream->skip(pos); + stream.skip(pos); } _LICbuffer = new byte[_numTracks * 22]; - stream->read(_LICbuffer, _numTracks * 22); - - delete stream; + stream.read(_LICbuffer, _numTracks * 22); } -void CDROM::freeLICbuffer() { +void CDROM::freeLICBuffer() { delete[] _LICbuffer; _LICbuffer = 0; } -void CDROM::playBgMusic() { - static const char *tracks[][2] = { - {"avt00.tot", "mine"}, - {"avt001.tot", "nuit"}, - {"avt002.tot", "campagne"}, - {"avt003.tot", "extsor1"}, - {"avt004.tot", "interieure"}, - {"avt005.tot", "zombie"}, - {"avt006.tot", "zombie"}, - {"avt007.tot", "campagne"}, - {"avt008.tot", "campagne"}, - {"avt009.tot", "extsor1"}, - {"avt010.tot", "extsor1"}, - {"avt011.tot", "interieure"}, - {"avt012.tot", "zombie"}, - {"avt014.tot", "nuit"}, - {"avt015.tot", "interieure"}, - {"avt016.tot", "statue"}, - {"avt017.tot", "zombie"}, - {"avt018.tot", "statue"}, - {"avt019.tot", "mine"}, - {"avt020.tot", "statue"}, - {"avt021.tot", "mine"}, - {"avt022.tot", "zombie"} - }; - - for (int i = 0; i < ARRAYSIZE(tracks); i++) - if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { - startTrack(tracks[i][1]); - break; - } -} - -void CDROM::playMultMusic() { - static const char *tracks[][6] = { - {"avt005.tot", "fra1", "all1", "ang1", "esp1", "ita1"}, - {"avt006.tot", "fra2", "all2", "ang2", "esp2", "ita2"}, - {"avt012.tot", "fra3", "all3", "ang3", "esp3", "ita3"}, - {"avt016.tot", "fra4", "all4", "ang4", "esp4", "ita4"}, - {"avt019.tot", "fra5", "all5", "ang5", "esp5", "ita5"}, - {"avt022.tot", "fra6", "all6", "ang6", "esp6", "ita6"} - }; - - // Default to "ang?" for other languages (including EN_USA) - int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2; - for (int i = 0; i < ARRAYSIZE(tracks); i++) - if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { - startTrack(tracks[i][language + 1]); - break; - } -} - void CDROM::startTrack(const char *trackName) { if (!_LICbuffer) return; - debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackName); - byte *matchPtr = getTrackBuffer(trackName); if (!matchPtr) { warning("Track \"%s\" not found", trackName); @@ -175,7 +101,7 @@ void CDROM::startTrack(const char *trackName) { play(start, end); - _startTime = _vm->_util->getTimeKey(); + _startTime = g_system->getMillis(); _trackStop = _startTime + (end - start + 1 + 150) * 40 / 3; } @@ -186,17 +112,19 @@ void CDROM::play(uint32 from, uint32 to) { // HSG encodes frame information into a double word: // minute multiplied by 4500, plus second multiplied by 75, // plus frame, minus 150 - debugC(1, kDebugMusic, "CDROM::play(%d, %d)", from, to); - AudioCD.play(1, 1, from, to - from + 1); _cdPlaying = true; } -int32 CDROM::getTrackPos(const char *keyTrack) { +bool CDROM::isPlaying() const { + return _cdPlaying; +} + +int32 CDROM::getTrackPos(const char *keyTrack) const { byte *keyBuffer = getTrackBuffer(keyTrack); - uint32 curPos = (_vm->_util->getTimeKey() - _startTime) * 3 / 40; + uint32 curPos = (g_system->getMillis() - _startTime) * 3 / 40; - if (_cdPlaying && (_vm->_util->getTimeKey() < _trackStop)) { + if (_cdPlaying && (g_system->getMillis() < _trackStop)) { if (keyBuffer && _curTrackBuffer && (keyBuffer != _curTrackBuffer)) { uint32 kStart = READ_LE_UINT32(keyBuffer + 12); uint32 kEnd = READ_LE_UINT32(keyBuffer + 16); @@ -216,7 +144,7 @@ int32 CDROM::getTrackPos(const char *keyTrack) { return -1; } -const char *CDROM::getCurTrack() { +const char *CDROM::getCurTrack() const { return _curTrack; } @@ -227,8 +155,6 @@ void CDROM::stopPlaying() { } void CDROM::stop() { - debugC(1, kDebugMusic, "CDROM::stop()"); - _curTrackBuffer = 0; AudioCD.stop(); _cdPlaying = false; @@ -248,7 +174,7 @@ void CDROM::testCD(int trySubst, const char *label) { // CD secor reading } -byte *CDROM::getTrackBuffer(const char *trackName) { +byte *CDROM::getTrackBuffer(const char *trackName) const { if (!_LICbuffer || !trackName) return 0; diff --git a/engines/gob/cdrom.h b/engines/gob/sound/cdrom.h index 25490de5dc..201f7adb75 100644 --- a/engines/gob/cdrom.h +++ b/engines/gob/sound/cdrom.h @@ -23,29 +23,30 @@ * */ -#ifndef GOB_CDROM_H -#define GOB_CDROM_H +#ifndef GOB_SOUND_CDROM_H +#define GOB_SOUND_CDROM_H + +#include "gob/dataio.h" namespace Gob { class CDROM { public: - bool _cdPlaying; + CDROM(); + ~CDROM(); - void readLIC(const char *fname); - void freeLICbuffer(); + void readLIC(DataStream &stream); + void freeLICBuffer(); void startTrack(const char *trackName); - void playBgMusic(); - void playMultMusic(); - void play(uint32 from, uint32 to); - int32 getTrackPos(const char *keyTrack = 0); - const char *getCurTrack(); void stopPlaying(); - void stop(); - void testCD(int trySubst, const char *label); - CDROM(GobEngine *vm); + bool isPlaying() const; + + int32 getTrackPos(const char *keyTrack = 0) const; + const char *getCurTrack() const; + + void testCD(int trySubst, const char *label); protected: byte *_LICbuffer; @@ -54,11 +55,14 @@ protected: uint16 _numTracks; uint32 _trackStop; uint32 _startTime; - GobEngine *_vm; + bool _cdPlaying; + + void play(uint32 from, uint32 to); + void stop(); - byte *getTrackBuffer(const char *trackName); + byte *getTrackBuffer(const char *trackName) const; }; } // End of namespace Gob -#endif // GOB_CDROM_H +#endif // GOB_SOUND_CDROM_H diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp new file mode 100644 index 0000000000..0b46f3485c --- /dev/null +++ b/engines/gob/sound/infogrames.cpp @@ -0,0 +1,103 @@ +/* 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 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 "gob/sound/infogrames.h" + +namespace Gob { + +Infogrames::Infogrames(Audio::Mixer &mixer) : _mixer(&mixer) { + _instruments = 0; + _song = 0; +} + +Infogrames::~Infogrames() { + clearSong(); + clearInstruments(); +} + +bool Infogrames::loadInstruments(const char *fileName) { + clearSong(); + clearInstruments(); + + return loadInst(fileName); +} + +bool Infogrames::loadSong(const char *fileName) { + clearSong(); + + if (!_instruments) + if (!loadInst("i1.ins")) + return false; + + _song = new Audio::Infogrames(*_instruments, true, + _mixer->getOutputRate(), _mixer->getOutputRate() / 75); + + if (!_song->load(fileName)) { + warning("Couldn't load infogrames music"); + clearSong(); + return false; + } + + return true; +} + +void Infogrames::play() { + if (_song && !_mixer->isSoundHandleActive(_handle)) { + _song->restart(); + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, + &_handle, _song, -1, 255, 0, false); + } +} + +void Infogrames::stop() { + _mixer->stopHandle(_handle); +} + +void Infogrames::clearInstruments() { + delete _instruments; + _instruments = 0; +} + +void Infogrames::clearSong() { + if (_song) { + _mixer->stopHandle(_handle); + + delete _song; + _song = 0; + } +} + +bool Infogrames::loadInst(const char *fileName) { + _instruments = new Audio::Infogrames::Instruments; + if (!_instruments->load(fileName)) { + warning("Couldn't load instruments file"); + clearInstruments(); + return false; + } + + return true; +} + +} // End of namespace Gob diff --git a/engines/cruise/stringSupport.cpp b/engines/gob/sound/infogrames.h index 7712f1e172..4a20dceb22 100644 --- a/engines/cruise/stringSupport.cpp +++ b/engines/gob/sound/infogrames.h @@ -23,8 +23,38 @@ * */ -#include "cruise/cruise_main.h" +#ifndef GOB_SOUND_INFOGRAMES_H +#define GOB_SOUND_INFOGRAMES_H -namespace Cruise { +#include "sound/mixer.h" +#include "sound/mods/infogrames.h" -} // End of namespace Cruise +namespace Gob { + +class Infogrames { +public: + Infogrames(Audio::Mixer &mixer); + ~Infogrames(); + + bool loadInstruments(const char *fileName); + bool loadSong(const char *fileName); + + void play(); + void stop(); + +private: + Audio::Mixer *_mixer; + + Audio::Infogrames::Instruments *_instruments; + Audio::Infogrames *_song; + Audio::SoundHandle _handle; + + void clearInstruments(); + void clearSong(); + + bool loadInst(const char *fileName); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_INFOGRAMES_H diff --git a/engines/gob/sound/pcspeaker.cpp b/engines/gob/sound/pcspeaker.cpp new file mode 100644 index 0000000000..0d1fc0a6db --- /dev/null +++ b/engines/gob/sound/pcspeaker.cpp @@ -0,0 +1,55 @@ +/* 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 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 "gob/sound/pcspeaker.h" + +namespace Gob { + +PCSpeaker::PCSpeaker(Audio::Mixer &mixer) : _mixer(&mixer) { + + _stream = new Audio::PCSpeaker(_mixer->getOutputRate()); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, + &_handle, _stream, -1, 50, 0, false, true); +} + +PCSpeaker::~PCSpeaker() { + _mixer->stopHandle(_handle); + delete _stream; +} + +void PCSpeaker::speakerOn(int16 frequency, int32 length) { + _stream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length); +} + +void PCSpeaker::speakerOff() { + _stream->stop(); +} + +void PCSpeaker::onUpdate(uint32 millis) { + if (_stream->isPlaying()) + _stream->stop(millis); +} + +} // End of namespace Gob diff --git a/engines/cruise/stringSupport.h b/engines/gob/sound/pcspeaker.h index c7cdb8efd9..8c4fb08021 100644 --- a/engines/cruise/stringSupport.h +++ b/engines/gob/sound/pcspeaker.h @@ -23,11 +23,30 @@ * */ -#ifndef CRUISE_STRING_SUPPORT_H -#define CRSUIE_STRING_SUPPORT_H +#ifndef GOB_SOUND_PCSPEAKER_H +#define GOB_SOUND_PCSPEAKER_H -namespace Cruise { +#include "sound/mixer.h" +#include "sound/softsynth/pcspk.h" -} // End of namespace Cruise +namespace Gob { -#endif +class PCSpeaker { +public: + PCSpeaker(Audio::Mixer &mixer); + ~PCSpeaker(); + + void speakerOn(int16 frequency, int32 length = -1); + void speakerOff(); + void onUpdate(uint32 millis); + +private: + Audio::Mixer *_mixer; + + Audio::PCSpeaker *_stream; + Audio::SoundHandle _handle; +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_PCSPEAKER_H diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp new file mode 100644 index 0000000000..2d2bf8e043 --- /dev/null +++ b/engines/gob/sound/sound.cpp @@ -0,0 +1,582 @@ +/* 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 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 "gob/gob.h" +#include "gob/sound/sound.h" +#include "gob/global.h" +#include "gob/util.h" +#include "gob/dataio.h" +#include "gob/game.h" +#include "gob/inter.h" + +namespace Gob { + +Sound::Sound(GobEngine *vm) : _vm(vm) { + _pcspeaker = new PCSpeaker(*_vm->_mixer); + _blaster = new SoundBlaster(*_vm->_mixer); + + _adlib = 0; + _infogrames = 0; + _cdrom = 0; + _bgatmos = 0; + + if (!_vm->_noMusic && _vm->hasAdlib()) + _adlib = new AdLib(*_vm->_mixer); + if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) + _infogrames = new Infogrames(*_vm->_mixer); + if (_vm->isCD()) + _cdrom = new CDROM; + if (_vm->getGameType() == kGameTypeWoodruff) + _bgatmos = new BackgroundAtmosphere(*_vm->_mixer); +} + +Sound::~Sound() { + delete _pcspeaker; + delete _blaster; + delete _adlib; + delete _infogrames; + delete _cdrom; + delete _bgatmos; + + for (int i = 0; i < kSoundsCount; i++) + _sounds[i].free(); +} + +void Sound::convToSigned(byte *buffer, int length) { + while (length-- > 0) + *buffer++ ^= 0x80; +} + +SoundDesc *Sound::sampleGetBySlot(int slot) { + if ((slot < 0) || (slot >= kSoundsCount)) + return 0; + + return &_sounds[slot]; +} + +const SoundDesc *Sound::sampleGetBySlot(int slot) const { + if ((slot < 0) || (slot >= kSoundsCount)) + return 0; + + return &_sounds[slot]; +} + +int Sound::sampleGetNextFreeSlot() const { + for (int i = 0; i < kSoundsCount; i++) + if (_sounds[i].empty()) + return i; + + return -1; +} + +bool Sound::sampleLoad(SoundDesc *sndDesc, const char *fileName, bool tryExist) { + if (!sndDesc) + return false; + + debugC(2, kDebugSound, "Loading sample \"%s\"", fileName); + + int16 handle = _vm->_dataIO->openData(fileName); + if (handle < 0) { + warning("Can't open sample file \"%s\"", fileName); + return false; + } + + _vm->_dataIO->closeData(handle); + + byte *data; + uint32 size; + + data = (byte *) _vm->_dataIO->getData(fileName); + if (!data) + return false; + + size = _vm->_dataIO->getDataSize(fileName); + sndDesc->load(SOUND_SND, SOUND_FILE, data, size); + + return true; +} + +void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) { + if (!sndDesc || sndDesc->empty()) + return; + + if (sndDesc->getType() == SOUND_ADL) { + + if (_adlib && noteAdlib) + if ((index == -1) || (_adlib->getIndex() == index)) + _adlib->stopPlay(); + + } else { + + if (_blaster) + _blaster->stopSound(0, sndDesc); + + } + + sndDesc->free(); +} + +void Sound::speakerOn(int16 frequency, int32 length) { + if (!_pcspeaker) + return; + + debugC(1, kDebugSound, "PCSpeaker: Playing tone (%d, %d)", frequency, length); + + _pcspeaker->speakerOn(frequency, length); +} + +void Sound::speakerOff() { + if (!_pcspeaker) + return; + + debugC(1, kDebugSound, "PCSpeaker: Stopping tone"); + + _pcspeaker->speakerOff(); +} + +void Sound::speakerOnUpdate(uint32 millis) { + if (!_pcspeaker) + return; + + _pcspeaker->onUpdate(millis); +} + +bool Sound::infogramesLoadInstruments(const char *fileName) { + if (!_infogrames) + return false; + + debugC(1, kDebugSound, "Infogrames: Loading instruments \"%s\"", fileName); + + return _infogrames->loadInstruments(fileName); +} + +bool Sound::infogramesLoadSong(const char *fileName) { + if (!_infogrames) + return false; + + debugC(1, kDebugSound, "Infogrames: Loading song \"%s\"", fileName); + + return _infogrames->loadSong(fileName); +} + +void Sound::infogramesPlay() { + if (!_infogrames) + return; + + debugC(1, kDebugSound, "Infogrames: Starting playback"); + + _infogrames->play(); +} + +void Sound::infogramesStop() { + if (!_infogrames) + return; + + debugC(1, kDebugSound, "Infogrames: Stopping playback"); + + _infogrames->stop(); +} + +bool Sound::adlibLoad(const char *fileName) { + if (!_adlib) + return false; + + debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName); + + return _adlib->load(fileName); +} + +bool Sound::adlibLoad(byte *data, uint32 size, int index) { + if (!_adlib) + return false; + + debugC(1, kDebugSound, "Adlib: Loading data (%d)", index); + + return _adlib->load(data, size, index); +} + +void Sound::adlibUnload() { + if (!_adlib) + return; + + debugC(1, kDebugSound, "Adlib: Unloading data"); + + _adlib->unload(); +} + +void Sound::adlibPlayTrack(const char *trackname) { + if (!_adlib || _adlib->isPlaying()) + return; + + debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname); + + _adlib->unload(); + _adlib->load(trackname); + _adlib->startPlay(); +} + +void Sound::adlibPlayBgMusic() { + if (!_adlib) + return; + + static const char *tracks[] = { +// "musmac1.adl", // TODO: This track isn't played correctly at all yet + "musmac2.adl", + "musmac3.adl", + "musmac4.adl", + "musmac5.adl", + "musmac6.adl" + }; + + int track = _vm->_util->getRandom(ARRAYSIZE(tracks)); + adlibPlayTrack(tracks[track]); +} + +void Sound::adlibPlay() { + if (!_adlib) + return; + + debugC(1, kDebugSound, "Adlib: Starting playback"); + + _adlib->startPlay(); +} + +void Sound::adlibStop() { + if (!_adlib) + return; + + debugC(1, kDebugSound, "Adlib: Stopping playback"); + + _adlib->stopPlay(); +} + +bool Sound::adlibIsPlaying() const { + if (!_adlib) + return false; + + return _adlib->isPlaying(); +} + +int Sound::adlibGetIndex() const { + if (!_adlib) + return -1; + + return _adlib->getIndex(); +} + +bool Sound::adlibGetRepeating() const { + if (!_adlib) + return false; + + return _adlib->getRepeating(); +} + +void Sound::adlibSetRepeating(int32 repCount) { + if (!_adlib) + return; + + _adlib->setRepeating(repCount); +} + +void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount, + int16 frequency, int16 fadeLength) { + if (!_blaster || !sndDesc) + return; + + debugC(1, kDebugSound, "SoundBlaster: Playing sample (%d, %d, %d)", + repCount, frequency, fadeLength); + + _blaster->playSample(*sndDesc, repCount, frequency, fadeLength); +} + +void Sound::blasterStop(int16 fadeLength, SoundDesc *sndDesc) { + if (!_blaster) + return; + + debugC(1, kDebugSound, "SoundBlaster: Stopping playback"); + + _blaster->stopSound(fadeLength, sndDesc); +} + +void Sound::blasterPlayComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs, int8 sndCount) { + if (!_blaster) + return; + + debugC(1, kDebugSound, "SoundBlaster: Playing composition (%d, %d)", + freqVal, sndCount); + + blasterWaitEndPlay(); + _blaster->stopComposition(); + + if (!sndDescs) + sndDescs = _sounds; + + _blaster->playComposition(composition, freqVal, sndDescs, sndCount); +} + +void Sound::blasterStopComposition() { + if (!_blaster) + return; + + debugC(1, kDebugSound, "SoundBlaster: Stopping composition"); + + _blaster->stopComposition(); +} + +char Sound::blasterPlayingSound() const { + if (!_blaster) + return 0; + + return _blaster->getPlayingSound(); +} + +void Sound::blasterSetRepeating(int32 repCount) { + if (!_blaster) + return; + + _blaster->setRepeating(repCount); +} + +void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) { + if (!_blaster) + return; + + debugC(1, kDebugSound, "SoundBlaster: Waiting for playback to end"); + + if (stopComp) + _blaster->endComposition(); + + while (_blaster->isPlaying() && !_vm->_quitRequested) { + if (interruptible && (_vm->_util->checkKey() == 0x11B)) { + WRITE_VAR(57, (uint32) -1); + return; + } + _vm->_util->longDelay(200); + } + + _blaster->stopSound(0); +} + +void Sound::cdLoadLIC(const char *fname) { + if (!_cdrom) + return; + + debugC(1, kDebugSound, "CDROM: Loading LIC \"%s\"", fname); + + int handle = _vm->_dataIO->openData(fname); + + if (handle == -1) + return; + + _vm->_dataIO->closeData(handle); + + _vm->_dataIO->getUnpackedData(fname); + + handle = _vm->_dataIO->openData(fname); + DataStream *stream = _vm->_dataIO->openAsStream(handle, true); + + _cdrom->readLIC(*stream); + + delete stream; +} + +void Sound::cdUnloadLIC() { + if (!_cdrom) + return; + + debugC(1, kDebugSound, "CDROM: Unloading LIC"); + + _cdrom->freeLICBuffer(); +} + +void Sound::cdPlayBgMusic() { + if (!_cdrom) + return; + + static const char *tracks[][2] = { + {"avt00.tot", "mine"}, + {"avt001.tot", "nuit"}, + {"avt002.tot", "campagne"}, + {"avt003.tot", "extsor1"}, + {"avt004.tot", "interieure"}, + {"avt005.tot", "zombie"}, + {"avt006.tot", "zombie"}, + {"avt007.tot", "campagne"}, + {"avt008.tot", "campagne"}, + {"avt009.tot", "extsor1"}, + {"avt010.tot", "extsor1"}, + {"avt011.tot", "interieure"}, + {"avt012.tot", "zombie"}, + {"avt014.tot", "nuit"}, + {"avt015.tot", "interieure"}, + {"avt016.tot", "statue"}, + {"avt017.tot", "zombie"}, + {"avt018.tot", "statue"}, + {"avt019.tot", "mine"}, + {"avt020.tot", "statue"}, + {"avt021.tot", "mine"}, + {"avt022.tot", "zombie"} + }; + + for (int i = 0; i < ARRAYSIZE(tracks); i++) + if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { + debugC(1, kDebugSound, "CDROM: Playing background music \"%s\" (\"%s\")", + tracks[i][1], _vm->_game->_curTotFile); + + _cdrom->startTrack(tracks[i][1]); + break; + } +} + +void Sound::cdPlayMultMusic() { + if (!_cdrom) + return; + + static const char *tracks[][6] = { + {"avt005.tot", "fra1", "all1", "ang1", "esp1", "ita1"}, + {"avt006.tot", "fra2", "all2", "ang2", "esp2", "ita2"}, + {"avt012.tot", "fra3", "all3", "ang3", "esp3", "ita3"}, + {"avt016.tot", "fra4", "all4", "ang4", "esp4", "ita4"}, + {"avt019.tot", "fra5", "all5", "ang5", "esp5", "ita5"}, + {"avt022.tot", "fra6", "all6", "ang6", "esp6", "ita6"} + }; + + // Default to "ang?" for other languages (including EN_USA) + int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2; + for (int i = 0; i < ARRAYSIZE(tracks); i++) + if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { + debugC(1, kDebugSound, "CDROM: Playing mult music \"%s\" (\"%s\")", + tracks[i][language + 1], _vm->_game->_curTotFile); + + _cdrom->startTrack(tracks[i][language + 1]); + break; + } +} + +void Sound::cdPlay(const char *trackName) { + if (!_cdrom) + return; + + debugC(1, kDebugSound, "CDROM: Playing track \"%s\"", trackName); + _cdrom->startTrack(trackName); +} + +void Sound::cdStop() { + if (!_cdrom) + return; + + debugC(1, kDebugSound, "CDROM: Stopping playback"); + _cdrom->stopPlaying(); +} + +bool Sound::cdIsPlaying() const { + if (!_cdrom) + return false; + + return _cdrom->isPlaying(); +} + +int32 Sound::cdGetTrackPos(const char *keyTrack) const { + if (!_cdrom) + return -1; + + return _cdrom->getTrackPos(keyTrack); +} + +const char *Sound::cdGetCurrentTrack() const { + if (!_cdrom) + return ""; + + return _cdrom->getCurTrack(); +} + +void Sound::cdTest(int trySubst, const char *label) { + if (!_cdrom) + return; + + _cdrom->testCD(trySubst, label); +} + +void Sound::bgPlay(const char *base, int count) { + if (!_bgatmos) + return; + + debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\" (%d)", base, count); + + _bgatmos->stop(); + _bgatmos->queueClear(); + + int length = strlen(base) + 7; + char *fileName = new char[length]; + SoundDesc *sndDesc; + + for (int i = 1; i <= count; i++) { + snprintf(fileName, length, "%s%02d.SND", base, i); + + sndDesc = new SoundDesc; + if (sampleLoad(sndDesc, fileName)) + _bgatmos->queueSample(*sndDesc); + } + + _bgatmos->play(); +} + +void Sound::bgStop() { + if (!_bgatmos) + return; + + debugC(1, kDebugSound, "BackgroundAtmosphere: Stopping playback"); + + _bgatmos->stop(); + _bgatmos->queueClear(); +} + +void Sound::bgSetPlayMode(BackgroundAtmosphere::PlayMode mode) { + if (!_bgatmos) + return; + + _bgatmos->setPlayMode(mode); +} + +void Sound::bgShade() { + if (!_bgatmos) + return; + + debugC(1, kDebugSound, "BackgroundAtmosphere: Shading playback"); + + _bgatmos->shade(); +} + +void Sound::bgUnshade() { + if (!_bgatmos) + return; + + debugC(1, kDebugSound, "BackgroundAtmosphere: Unshading playback"); + + _bgatmos->unshade(); +} + +} // End of namespace Gob diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h new file mode 100644 index 0000000000..b59510e4bb --- /dev/null +++ b/engines/gob/sound/sound.h @@ -0,0 +1,147 @@ +/* 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 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$ + * + */ + +#ifndef GOB_SOUND_SOUND_H +#define GOB_SOUND_SOUND_H + +#include "gob/sound/sounddesc.h" +#include "gob/sound/pcspeaker.h" +#include "gob/sound/soundblaster.h" +#include "gob/sound/adlib.h" +#include "gob/sound/infogrames.h" +#include "gob/sound/cdrom.h" +#include "gob/sound/bgatmosphere.h" + +namespace Gob { + +class Sound { +public: + static const int kSoundsCount = 60; + + Sound(GobEngine *vm); + ~Sound(); + + static void convToSigned(byte *buffer, int length); + + // Samples + SoundDesc *sampleGetBySlot(int slot); + const SoundDesc *sampleGetBySlot(int slot) const; + int sampleGetNextFreeSlot() const; + + bool sampleLoad(SoundDesc *sndDesc, const char *fileName, bool tryExist = true); + void sampleFree(SoundDesc *sndDesc, bool noteAdlib = false, int index = -1); + + + // SoundBlaster + void blasterPlay(SoundDesc *sndDesc, int16 repCount, + int16 frequency, int16 fadeLength = 0); + void blasterStop(int16 fadeLength, SoundDesc *sndDesc = 0); + + void blasterPlayComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs = 0, int8 sndCount = kSoundsCount); + void blasterStopComposition(); + + char blasterPlayingSound() const; + + void blasterSetRepeating(int32 repCount); + void blasterWaitEndPlay(bool interruptible = false, bool stopComp = true); + + + // PCSpeaker + void speakerOn(int16 frequency, int32 length = -1); + void speakerOff(); + void speakerOnUpdate(uint32 millis); + + + // AdLib + bool adlibLoad(const char *fileName); + bool adlibLoad(byte *data, uint32 size, int index = -1); + void adlibUnload(); + + void adlibPlayTrack(const char *trackname); + void adlibPlayBgMusic(); + + void adlibPlay(); + void adlibStop(); + + bool adlibIsPlaying() const; + + int adlibGetIndex() const; + bool adlibGetRepeating() const; + + void adlibSetRepeating(int32 repCount); + + + // Infogrames + bool infogramesLoadInstruments(const char *fileName); + bool infogramesLoadSong(const char *fileName); + + void infogramesPlay(); + void infogramesStop(); + + + // CD-ROM + void cdLoadLIC(const char *fname); + void cdUnloadLIC(); + + void cdPlayBgMusic(); + void cdPlayMultMusic(); + + void cdPlay(const char *trackName); + void cdStop(); + + bool cdIsPlaying() const; + + int32 cdGetTrackPos(const char *keyTrack = 0) const; + const char *cdGetCurrentTrack() const; + + void cdTest(int trySubst, const char *label); + + + // Background Atmosphere + void bgPlay(const char *base, int count); + void bgStop(); + + void bgSetPlayMode(BackgroundAtmosphere::PlayMode mode); + + void bgShade(); + void bgUnshade(); + +private: + GobEngine *_vm; + + SoundDesc _sounds[kSoundsCount]; + + PCSpeaker *_pcspeaker; + SoundBlaster *_blaster; + AdLib *_adlib; + Infogrames *_infogrames; + CDROM *_cdrom; + BackgroundAtmosphere *_bgatmos; +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_H diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp new file mode 100644 index 0000000000..eeedfaa3cb --- /dev/null +++ b/engines/gob/sound/soundblaster.cpp @@ -0,0 +1,126 @@ +/* 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 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 "gob/sound/soundblaster.h" + +namespace Gob { + +SoundBlaster::SoundBlaster(Audio::Mixer &mixer) : SoundMixer(mixer, Audio::Mixer::kSFXSoundType) { + _curSoundDesc = 0; + + _compositionSamples = 0; + _compositionSampleCount = 0; + _compositionPos = -1; +} + +SoundBlaster::~SoundBlaster() { +} + +void SoundBlaster::playSample(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength) { + SoundMixer::play(sndDesc, repCount, frequency, fadeLength); +} + +void SoundBlaster::stopSound(int16 fadeLength, SoundDesc *sndDesc) { + Common::StackLock slock(_mutex); + + if (sndDesc && (sndDesc != _curSoundDesc)) + return; + + if (fadeLength <= 0) + _curSoundDesc = 0; + + SoundMixer::stop(fadeLength); +} + +void SoundBlaster::stopComposition() { + if (_compositionPos != -1) { + stopSound(0); + _compositionPos = -1; + } +} + +void SoundBlaster::endComposition() { + _compositionPos = -1; +} + +void SoundBlaster::nextCompositionPos() { + int8 slot; + + while ((++_compositionPos < 50) && + ((slot = _composition[_compositionPos]) != -1)) { + if ((slot >= 0) && (slot < _compositionSampleCount)) { + SoundDesc &sample = _compositionSamples[slot]; + if (!sample.empty() && (sample.getType() == SOUND_SND)) { + setSample(sample, 1, 0, 0); + return; + } + } + if (_compositionPos == 49) + _compositionPos = -1; + } + _compositionPos = -1; +} + +void SoundBlaster::playComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs, int8 sndCount) { + + _compositionSamples = sndDescs; + _compositionSampleCount = sndCount; + + int i = -1; + do { + i++; + _composition[i] = composition[i]; + } while ((i < 50) && (composition[i] != -1)); + + _compositionPos = -1; + nextCompositionPos(); +} + +void SoundBlaster::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, + int16 fadeLength) { + + _curSoundDesc = &sndDesc; + SoundMixer::setSample(sndDesc, repCount, frequency, fadeLength); +} + +void SoundBlaster::checkEndSample() { + if (_compositionPos != -1) + nextCompositionPos(); + else + SoundMixer::checkEndSample(); +} + +void SoundBlaster::endFade() { + if (_fadeVolStep > 0) { + _compositionPos = -1; + _curSoundDesc = 0; + } + + SoundMixer::endFade(); +} + +} // End of namespace Gob diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h new file mode 100644 index 0000000000..c57e4a443e --- /dev/null +++ b/engines/gob/sound/soundblaster.h @@ -0,0 +1,71 @@ +/* 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 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$ + * + */ + +#ifndef GOB_SOUND_SOUNDBLASTER_H +#define GOB_SOUND_SOUNDBLASTER_H + +#include "common/mutex.h" +#include "sound/mixer.h" + +#include "gob/sound/sounddesc.h" +#include "gob/sound/soundmixer.h" + +namespace Gob { + +class SoundBlaster : public SoundMixer { +public: + SoundBlaster(Audio::Mixer &mixer); + ~SoundBlaster(); + + void playSample(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength = 0); + void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0); + + void playComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs = 0, int8 sndCount = 60); + void stopComposition(); + void endComposition(); + +protected: + Common::Mutex _mutex; + + SoundDesc *_compositionSamples; + int8 _compositionSampleCount; + int16 _composition[50]; + int8 _compositionPos; + + SoundDesc *_curSoundDesc; + + void setSample(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength); + void checkEndSample(); + void endFade(); + + void nextCompositionPos(); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_SOUNDBLASTER_H diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp new file mode 100644 index 0000000000..e0885d9faa --- /dev/null +++ b/engines/gob/sound/sounddesc.cpp @@ -0,0 +1,116 @@ +/* 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 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/util.h" + +#include "gob/sound/sounddesc.h" + +namespace Gob { + +SoundDesc::SoundDesc() { + _data = _dataPtr = 0; + _size = 0; + + _type = SOUND_SND; + _source = SOUND_FILE; + + _repCount = 0; + _frequency = 0; + _flag = 0; + _id = 0; +} + +SoundDesc::~SoundDesc() { + free(); +} + +void SoundDesc::set(SoundType type, SoundSource src, + byte *data, uint32 dSize) { + + free(); + + _type = type; + _source = src; + _data = _dataPtr = data; + _size = dSize; +} + +void SoundDesc::load(SoundType type, SoundSource src, + byte *data, uint32 dSize) { + + free(); + + _source = src; + switch (type) { + case SOUND_ADL: + loadADL(data, dSize); + break; + case SOUND_SND: + loadSND(data, dSize); + break; + } +} + +void SoundDesc::free() { + if (_source != SOUND_TOT) + delete[] _data; + _data = _dataPtr = 0; + _id = 0; +} + +void SoundDesc::convToSigned() { + if ((_type == SOUND_SND) && _data && _dataPtr) + for (uint32 i = 0; i < _size; i++) + _dataPtr[i] ^= 0x80; +} + +int16 SoundDesc::calcFadeOutLength(int16 frequency) { + return (10 * (_size / 2)) / frequency; +} + +uint32 SoundDesc::calcLength(int16 repCount, int16 frequency, bool fade) { + uint32 fadeSize = fade ? _size / 2 : 0; + return ((_size * repCount - fadeSize) * 1000) / frequency; +} + +void SoundDesc::loadSND(byte *data, uint32 dSize) { + assert(dSize > 6); + + _type = SOUND_SND; + _data = data; + _dataPtr = data + 6; + _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700); + _flag = data[0] ? (data[0] & 0x7F) : 8; + data[0] = 0; + _size = MIN(READ_BE_UINT32(data), dSize - 6); +} + +void SoundDesc::loadADL(byte *data, uint32 dSize) { + _type = SOUND_ADL; + _data = _dataPtr = data; + _size = dSize; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/sounddesc.h b/engines/gob/sound/sounddesc.h new file mode 100644 index 0000000000..ed4447254c --- /dev/null +++ b/engines/gob/sound/sounddesc.h @@ -0,0 +1,85 @@ +/* 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 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$ + * + */ + +#ifndef GOB_SOUND_SOUNDDESC_H +#define GOB_SOUND_SOUNDDESC_H + +#include "common/endian.h" + +namespace Gob { + +enum SoundType { + SOUND_SND, + SOUND_ADL +}; + +enum SoundSource { + SOUND_FILE, + SOUND_TOT, + SOUND_EXT +}; + +class SoundDesc { +public: + int16 _repCount; + int16 _frequency; + int16 _flag; + int16 _id; + + byte *getData() { return _dataPtr; } + + uint32 size() const { return _size; } + bool empty() const { return !_dataPtr; } + SoundType getType() const { return _type; } + + bool isId(int16 id) const { return _dataPtr && (_id == id); } + + void set(SoundType type, SoundSource src, byte *data, uint32 dSize); + void load(SoundType type, SoundSource src, byte *data, uint32 dSize); + void free(); + void convToSigned(); + + // Which fade out length to use when the fade starts half-way through? + int16 calcFadeOutLength(int16 frequency); + uint32 calcLength(int16 repCount, int16 frequency, bool fade); + + SoundDesc(); + ~SoundDesc(); + +private: + byte *_data; + byte *_dataPtr; + uint32 _size; + + SoundType _type; + SoundSource _source; + + void loadSND(byte *data, uint32 dSize); + void loadADL(byte *data, uint32 dSize); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_SOUNDDESC_H diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp new file mode 100644 index 0000000000..1a287d782f --- /dev/null +++ b/engines/gob/sound/soundmixer.cpp @@ -0,0 +1,204 @@ +/* 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 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 "gob/sound/soundmixer.h" + +namespace Gob { + +SoundMixer::SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type) : _mixer(&mixer) { + _playingSound = 0; + + _rate = _mixer->getOutputRate(); + _end = true; + _data = 0; + _length = 0; + _freq = 0; + _repCount = 0; + + _offset = 0; + _offsetFrac = 0; + _offsetInc = 0; + + _cur = 0; + _last = 0; + + _fade = false; + _fadeVol = 65536; + _fadeVolStep = 0; + _fadeSamples = 0; + _curFadeSamples = 0; + + _mixer->playInputStream(type, &_handle, this, -1, 255, 0, false, true); +} + +SoundMixer::~SoundMixer() { + _mixer->stopHandle(_handle); +} + +bool SoundMixer::isPlaying() const { + return !_end; +} + +char SoundMixer::getPlayingSound() const { + return _playingSound; +} + +void SoundMixer::stop(int16 fadeLength) { + Common::StackLock slock(_mutex); + + if (fadeLength <= 0) { + _data = 0; + _end = true; + _playingSound = 0; + return; + } + + _fade = true; + _fadeVol = 65536; + _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); + _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples)); + _curFadeSamples = 0; +} + +void SoundMixer::setRepeating(int32 repCount) { + Common::StackLock slock(_mutex); + + _repCount = repCount; +} + +void SoundMixer::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, + int16 fadeLength) { + + if (frequency <= 0) + frequency = sndDesc._frequency; + + sndDesc._repCount = repCount - 1; + sndDesc._frequency = frequency; + + _data = (int8 *) sndDesc.getData(); + _length = sndDesc.size(); + _freq = frequency; + + _repCount = repCount; + _end = false; + _playingSound = 1; + + _offset = 0; + _offsetFrac = 0; + _offsetInc = (_freq << FRAC_BITS) / _rate; + + _last = _cur; + _cur = _data[0]; + + _curFadeSamples = 0; + if (fadeLength == 0) { + _fade = false; + _fadeVol = 65536; + _fadeSamples = 0; + _fadeVolStep = 0; + } else { + _fade = true; + _fadeVol = 0; + _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); + _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples)); + } +} + +void SoundMixer::play(SoundDesc &sndDesc, int16 repCount, int16 frequency, + int16 fadeLength) { + Common::StackLock slock(_mutex); + + if (!_end) + return; + + setSample(sndDesc, repCount, frequency, fadeLength); +} + +void SoundMixer::checkEndSample() { + if ((_repCount == -1) || (--_repCount > 0)) { + _offset = 0; + _offsetFrac = 0; + _end = false; + _playingSound = 1; + } else { + _end = true; + _playingSound = 0; + } +} + +int SoundMixer::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock slock(_mutex); + + for (int i = 0; i < numSamples; i++) { + if (!_data) + return i; + if (_end || (_offset >= _length)) + checkEndSample(); + if (_end) + return i; + + // Linear interpolation. See sound/rate.cpp + + int16 val = (_last + (((_cur - _last) * _offsetFrac + + FRAC_HALF) >> FRAC_BITS)) << 8; + *buffer++ = (val * _fadeVol) >> 16; + + _offsetFrac += _offsetInc; + + // Was there an integral change? + if (fracToInt(_offsetFrac) > 0) { + _last = _cur; + _cur = _data[_offset]; + _offset += fracToInt(_offsetFrac); + _offsetFrac &= FRAC_LO_MASK; + } + + if (_fade) { + + if (++_curFadeSamples >= _fadeSamples) + endFade(); + else + _fadeVol -= _fadeVolStep; + + if (_fadeVol < 0) + _fadeVol = 0; + + } + } + return numSamples; +} + +void SoundMixer::endFade() { + if (_fadeVolStep > 0) { + _data = 0; + _end = true; + _playingSound = 0; + } else { + _fadeVol = 65536; + _fade = false; + } +} + +} // End of namespace Gob diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h new file mode 100644 index 0000000000..5789885a99 --- /dev/null +++ b/engines/gob/sound/soundmixer.h @@ -0,0 +1,95 @@ +/* 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 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$ + * + */ + +#ifndef GOB_SOUND_SOUNDMIXER_H +#define GOB_SOUND_SOUNDMIXER_H + +#include "common/mutex.h" +#include "common/frac.h" +#include "sound/audiostream.h" +#include "sound/mixer.h" + +#include "gob/sound/sounddesc.h" + +namespace Gob { + +class SoundMixer : public Audio::AudioStream { +public: + SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType); + ~SoundMixer(); + + virtual void play(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength = 0); + virtual void stop(int16 fadeLength); + + bool isPlaying() const; + char getPlayingSound() const; + + void setRepeating(int32 repCount); + + int readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return false; } + bool endOfData() const { return _end; } + bool endOfStream() const { return false; } + int getRate() const { return _rate; } + +protected: + Audio::Mixer *_mixer; + + Audio::SoundHandle _handle; + Common::Mutex _mutex; + + bool _end; + int8 *_data; + uint32 _length; + uint32 _rate; + int32 _freq; + int32 _repCount; + + uint32 _offset; + frac_t _offsetFrac; + frac_t _offsetInc; + + int16 _cur; + int16 _last; + + bool _fade; + int32 _fadeVol; + int32 _fadeVolStep; + uint8 _fadeLength; + uint32 _fadeSamples; + uint32 _curFadeSamples; + + char _playingSound; + + virtual void setSample(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength); + virtual void checkEndSample(); + virtual void endFade(); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_SOUNDMIXER_H diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index 8e573ddb1a..4987426fe0 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -23,7 +23,6 @@ * */ - #include "common/events.h" #include "gob/gob.h" @@ -32,8 +31,8 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/sound.h" #include "gob/video.h" +#include "gob/sound/sound.h" namespace Gob { @@ -60,7 +59,7 @@ void Util::beep(int16 freq) { if (_vm->_global->_soundFlags == 0) return; - _vm->_snd->speakerOn(freq, 50); + _vm->_sound->speakerOn(freq, 50); } void Util::delay(uint16 msecs) { diff --git a/engines/gob/variables.cpp b/engines/gob/variables.cpp new file mode 100644 index 0000000000..0eea2f6547 --- /dev/null +++ b/engines/gob/variables.cpp @@ -0,0 +1,311 @@ +/* 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 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/endian.h" + +#include "gob/gob.h" +#include "gob/variables.h" + +namespace Gob { + +Variables::Variables(uint32 size) { + _size = size; + + _vars = new byte[_size]; + _sizes = new byte[_size]; + + clear(); +} + +Variables::~Variables() { + delete[] _vars; + delete[] _sizes; +} + +void Variables::clear() { + memset(_vars, 0, _size); + + // All variables are 32 bit wide per default + memset(_sizes, 0, _size); + for (uint32 i = 0; i < _size; i += 4) + _sizes[i] = kSize32; +} + +void Variables::clearSize(uint32 offset) { + uint32 inVar = offset % 4; + uint32 varOff = (offset >> 2) << 2; + + // Clearing out the old size + for (uint32 i = 0; i < 4; i++) { + if (_sizes[varOff + i] == kSize32) + _sizes[varOff + i] = kSize8; + else if ((inVar == (i + 1)) && (_sizes[varOff + i] == kSize16)) + _sizes[varOff + i] = kSize8; + } +} + +void Variables::writeSize(uint32 offset, byte n) { + clearSize(offset); + + _sizes[offset] = n; + // Setting following bytes of size to 8 bit, for easy clearing out afterwards + for (; n > 0; n--) + _sizes[offset + n] = kSize8; +} + +void Variables::writeSizeString(uint32 offset, uint32 length) { + clearSize(offset); + + memset(_sizes + offset, kSize8, length); +} + +void Variables::writeVar8(uint32 var, uint8 value) { + writeOff8(var * 4, value); +} + +void Variables::writeVar16(uint32 var, uint16 value) { + writeOff16(var * 4, value); +} + +void Variables::writeVar32(uint32 var, uint32 value) { + writeOff32(var * 4, value); +} + +void Variables::writeVarString(uint32 var, const char *value) { + writeOffString(var * 4, value); +} + +void Variables::writeOff8(uint32 offset, uint8 value) { + write8(_vars + offset, value); + writeSize(offset, kSize8); +} + +void Variables::writeOff16(uint32 offset, uint16 value) { + write16(_vars + offset, value); + writeSize(offset, kSize16); +} + +void Variables::writeOff32(uint32 offset, uint32 value) { + write32(_vars + offset, value); + writeSize(offset, kSize32); +} + +void Variables::writeOffString(uint32 offset, const char *value) { + strcpy((char *) (_vars + offset), value); + writeSizeString(offset, strlen(value)); +} + +uint8 Variables::readVar8(uint32 var) const { + return readOff8(var * 4); +} + +uint16 Variables::readVar16(uint32 var) const { + return readOff16(var * 4); +} + +uint32 Variables::readVar32(uint32 var) const { + return readOff32(var * 4); +} + +void Variables::readVarString(uint32 var, char *value, uint32 length) { + readOffString(var * 4, value, length); +} + +uint8 Variables::readOff8(uint32 offset) const { + return read8(_vars + offset); +} + +uint16 Variables::readOff16(uint32 offset) const { + return read16(_vars + offset); +} + +uint32 Variables::readOff32(uint32 offset) const { + return read32(_vars + offset); +} + +void Variables::readOffString(uint32 offset, char *value, uint32 length) { + strncpy0(value, (const char *) (_vars + offset), length - 1); +} + +const uint8 *Variables::getAddressVar8(uint32 var) const { + return getAddressOff8(var * 4); +} + +uint8 *Variables::getAddressVar8(uint32 var, uint32 n) { + return getAddressOff8(var * 4, n); +} + +const uint16 *Variables::getAddressVar16(uint32 var) const { + return getAddressOff16(var * 4); +} + +uint16 *Variables::getAddressVar16(uint32 var, uint32 n) { + return getAddressOff16(var * 4, n); +} + +const uint32 *Variables::getAddressVar32(uint32 var) const { + return getAddressOff32(var * 4); +} + +uint32 *Variables::getAddressVar32(uint32 var, uint32 n) { + return getAddressOff32(var * 4, n); +} + +const char *Variables::getAddressVarString(uint32 var) const { + return getAddressOffString(var * 4); +} + +char *Variables::getAddressVarString(uint32 var, uint32 n) { + return getAddressOffString(var * 4, n); +} + +const uint8 *Variables::getAddressOff8(uint32 offset) const { + return ((const uint8 *) (_vars + offset)); +} + +uint8 *Variables::getAddressOff8(uint32 offset, uint32 n) { + for (uint32 i = 0; i < n; i++) + writeSize(offset + i, kSize8); + + return ((uint8 *) (_vars + offset)); +} + +const uint16 *Variables::getAddressOff16(uint32 offset) const { + return ((const uint16 *) (_vars + offset)); +} + +uint16 *Variables::getAddressOff16(uint32 offset, uint32 n) { + for (uint32 i = 0; i < n; i++) + writeSize(offset + i * 2, kSize16); + + return ((uint16 *) (_vars + offset)); +} + +const uint32 *Variables::getAddressOff32(uint32 offset) const { + return ((const uint32 *) (_vars + offset)); +} + +uint32 *Variables::getAddressOff32(uint32 offset, uint32 n) { + for (uint32 i = 0; i < n; i++) + writeSize(offset + i * 4, kSize32); + + return ((uint32 *) (_vars + offset)); +} + +const char *Variables::getAddressOffString(uint32 offset) const { + return ((const char *) (_vars + offset)); +} + +char *Variables::getAddressOffString(uint32 offset, uint32 n) { + writeSizeString(offset, (n == 0xFFFFFFFF) ? strlen((char *) (_vars + offset)) : n); + + return ((char *) (_vars + offset)); +} + +bool Variables::copyTo(uint32 offset, byte *variables, byte *sizes, uint32 n) const { + if ((offset + n) > _size) + return false; + + if (variables) + memcpy(variables, _vars + offset, n); + if (sizes) + memcpy(sizes, _sizes + offset, n); + + return true; +} + +bool Variables::copyFrom(uint32 offset, const byte *variables, const byte *sizes, uint32 n) { + if (((offset + n) > _size) || !variables || !sizes) + return false; + + memcpy(_vars + offset, variables, n); + memcpy(_sizes + offset, sizes, n); + + return true; +} + + +VariablesLE::VariablesLE(uint32 size) : Variables(size) { +} + +VariablesLE::~VariablesLE() { +} + +void VariablesLE::write8(byte *buf, uint8 data) const { + *buf = (byte) data; +} + +void VariablesLE::write16(byte *buf, uint16 data) const { + WRITE_LE_UINT16(buf, data); +} + +void VariablesLE::write32(byte *buf, uint32 data) const { + WRITE_LE_UINT32(buf, data); +} + +uint8 VariablesLE::read8(const byte *buf) const { + return (uint8) *buf; +} + +uint16 VariablesLE::read16(const byte *buf) const { + return READ_LE_UINT16(buf); +} + +uint32 VariablesLE::read32(const byte *buf) const { + return READ_LE_UINT32(buf); +} + + +VariablesBE::VariablesBE(uint32 size) : Variables(size) { +} + +VariablesBE::~VariablesBE() { +} + +void VariablesBE::write8(byte *buf, uint8 data) const { + *buf = (byte) data; +} + +void VariablesBE::write16(byte *buf, uint16 data) const { + WRITE_BE_UINT16(buf, data); +} + +void VariablesBE::write32(byte *buf, uint32 data) const { + WRITE_BE_UINT32(buf, data); +} + +uint8 VariablesBE::read8(const byte *buf) const { + return (uint8) *buf; +} + +uint16 VariablesBE::read16(const byte *buf) const { + return READ_BE_UINT16(buf); +} + +uint32 VariablesBE::read32(const byte *buf) const { + return READ_BE_UINT32(buf); +} + +} // End of namespace Gob diff --git a/engines/gob/variables.h b/engines/gob/variables.h new file mode 100644 index 0000000000..5989ed38ee --- /dev/null +++ b/engines/gob/variables.h @@ -0,0 +1,147 @@ +/* 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 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$ + * + */ + +#ifndef GOB_VARIABLES_H +#define GOB_VARIABLES_H + +namespace Gob { + +class Variables { +public: + Variables(uint32 size); + virtual ~Variables(); + + void writeVar8(uint32 var, uint8 value); + void writeVar16(uint32 var, uint16 value); + void writeVar32(uint32 var, uint32 value); + + void writeVarString(uint32 var, const char *value); + + void writeOff8(uint32 offset, uint8 value); + void writeOff16(uint32 offset, uint16 value); + void writeOff32(uint32 offset, uint32 value); + + void writeOffString(uint32 offset, const char *value); + + uint8 readVar8(uint32 var) const; + uint16 readVar16(uint32 var) const; + uint32 readVar32(uint32 var) const; + + void readVarString(uint32 var, char *value, uint32 length); + + uint8 readOff8(uint32 offset) const; + uint16 readOff16(uint32 offset) const; + uint32 readOff32(uint32 offset) const; + + void readOffString(uint32 offset, char *value, uint32 length); + + + const uint8 *getAddressVar8(uint32 var) const; + uint8 *getAddressVar8(uint32 var, uint32 n = 1); + + const uint16 *getAddressVar16(uint32 var) const; + uint16 *getAddressVar16(uint32 var, uint32 n = 1); + + const uint32 *getAddressVar32(uint32 var) const; + uint32 *getAddressVar32(uint32 var, uint32 n = 1); + + const char *getAddressVarString(uint32 var) const; + char *getAddressVarString(uint32 var, uint32 n = 0xFFFFFFFF); + + const uint8 *getAddressOff8(uint32 offset) const; + uint8 *getAddressOff8(uint32 offset, uint32 n = 1); + + const uint16 *getAddressOff16(uint32 offset) const; + uint16 *getAddressOff16(uint32 offset, uint32 n = 1); + + const uint32 *getAddressOff32(uint32 offset) const; + uint32 *getAddressOff32(uint32 offset, uint32 n = 1); + + const char *getAddressOffString(uint32 offset) const; + char *getAddressOffString(uint32 offset, uint32 n = 0xFFFFFFFF); + + + bool copyTo(uint32 offset, byte *variables, byte *sizes, uint32 n) const; + bool copyFrom(uint32 offset, const byte *variables, const byte *sizes, uint32 n); + +protected: + virtual void write8(byte *buf, uint8 data) const = 0; + virtual void write16(byte *buf, uint16 data) const = 0; + virtual void write32(byte *buf, uint32 data) const = 0; + + virtual uint8 read8(const byte *buf) const = 0; + virtual uint16 read16(const byte *buf) const = 0; + virtual uint32 read32(const byte *buf) const = 0; + +private: + // Basically the number of additional bytes occupied + static const byte kSize8 = 0; + static const byte kSize16 = 1; + static const byte kSize32 = 3; + + uint32 _size; + + byte *_vars; + byte *_sizes; + + void clear(); + void clearSize(uint32 offset); + void writeSize(uint32 offset, byte n); + void writeSizeString(uint32 offset, uint32 length); +}; + +class VariablesLE : public Variables { +public: + VariablesLE(uint32 size); + ~VariablesLE(); + +protected: + void write8(byte *buf, uint8 data) const; + void write16(byte *buf, uint16 data) const; + void write32(byte *buf, uint32 data) const; + + uint8 read8(const byte *buf) const; + uint16 read16(const byte *buf) const; + uint32 read32(const byte *buf) const; +}; + +class VariablesBE : public Variables { +public: + VariablesBE(uint32 size); + ~VariablesBE(); + +protected: + void write8(byte *buf, uint8 data) const; + void write16(byte *buf, uint16 data) const; + void write32(byte *buf, uint32 data) const; + + uint8 read8(const byte *buf) const; + uint16 read16(const byte *buf) const; + uint32 read32(const byte *buf) const; +}; + +} // End of namespace Gob + +#endif // GOB_VARIABLES_H diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index 9a004318b8..453613d1ae 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/cursorman.h" @@ -87,10 +86,14 @@ void SurfaceDesc::swap(SurfaceDesc &surf) { Video::Video(GobEngine *vm) : _vm(vm) { _doRangeClamp = false; _videoDriver = 0; + _surfWidth = 320; _surfHeight = 200; + _scrollOffsetX = 0; _scrollOffsetY = 0; + + _splitSurf = 0; _splitHeight1 = 200; _splitHeight2 = 0; _splitStart = 0; @@ -179,21 +182,34 @@ void Video::retrace(bool mouse) { int screenOffset = _scrollOffsetY * _surfWidth + _scrollOffsetX; int screenX = _screenDeltaX; int screenY = _screenDeltaY; - int screenWidth = _vm->_width; - int screenHeight = _splitHeight1; + int screenWidth = MIN<int>(_surfWidth - _scrollOffsetX, _vm->_width); + int screenHeight = MIN<int>(_surfHeight - _splitHeight2 - _scrollOffsetY, _vm->_height); g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() + screenOffset, _surfWidth, screenX, screenY, screenWidth, screenHeight); - if (_splitHeight2 > 0) { + if (_splitSurf) { + + screenOffset = 0; + screenX = 0; + screenY = _vm->_height - _splitSurf->getHeight(); + screenWidth = MIN<int>(_vm->_width, _splitSurf->getWidth()); + screenHeight = _splitSurf->getHeight(); + + g_system->copyRectToScreen(_splitSurf->getVidMem() + screenOffset, + _splitSurf->getWidth(), screenX, screenY, screenWidth, screenHeight); + + } else if (_splitHeight2 > 0) { + screenOffset = _splitStart * _surfWidth; screenX = 0; screenY = _vm->_height - _splitHeight2; - screenWidth = _vm->_width; + screenWidth = MIN<int>(_surfWidth, _vm->_width); screenHeight = _splitHeight2; g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() + screenOffset, _surfWidth, screenX, screenY, screenWidth, screenHeight); + } g_system->updateScreen(); diff --git a/engines/gob/video.h b/engines/gob/video.h index 4a585d8857..1338885588 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -37,10 +37,11 @@ class SurfaceDesc : public ReferenceCounter<SurfaceDesc> { public: int16 _vidMode; - int16 getWidth() { return _width; } - int16 getHeight() { return _height; } + int16 getWidth() const { return _width; } + int16 getHeight() const { return _height; } byte *getVidMem() { return _vidMem; } - bool hasOwnVidMem() { return _ownVidMem; } + const byte *getVidMem() const { return _vidMem; } + bool hasOwnVidMem() const { return _ownVidMem; } void setVidMem(byte *vidMem); void resize(int16 width, int16 height); @@ -97,13 +98,18 @@ public: }; bool _doRangeClamp; + int16 _surfWidth; int16 _surfHeight; + int16 _scrollOffsetX; int16 _scrollOffsetY; + + SurfaceDesc::Ptr _splitSurf; int16 _splitHeight1; int16 _splitHeight2; int16 _splitStart; + int16 _screenDeltaX; int16 _screenDeltaY; diff --git a/engines/gob/video_v1.cpp b/engines/gob/video_v1.cpp index 4ed3b04bad..3c9627c041 100644 --- a/engines/gob/video_v1.cpp +++ b/engines/gob/video_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/video_v2.cpp b/engines/gob/video_v2.cpp index 52b349ca67..ab0c7e52db 100644 --- a/engines/gob/video_v2.cpp +++ b/engines/gob/video_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index e088646498..909d39a63b 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -33,6 +33,7 @@ #include "gob/palanim.h" #include "gob/inter.h" #include "gob/map.h" +#include "gob/sound/sound.h" namespace Gob { @@ -289,6 +290,8 @@ void VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey, if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame)) break; + evalBgShading(video); + if (fade) { _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); fade = false; @@ -299,18 +302,27 @@ void VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey, startFrame++; } + evalBgShading(video); + if (reverseTo >= 0) { int16 toFrame = video.getFramesCount() - reverseTo; for (int i = video.getCurrentFrame(); i >= toFrame; i--) { video.seekFrame(i, SEEK_SET, true); - if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) { + + bool b = doPlay(i, breakKey, 0, 0, 0, 0, 0); + evalBgShading(video); + + if (b) { _vm->_palAnim->fade(0, -2, 0); memset((char *) _vm->_draw->_vgaPalette, 0, 768); } + if (!_noCursorSwitch) video.waitEndFrame(); } } + + evalBgShading(video); } void VideoPlayer::primaryClose() { @@ -334,17 +346,32 @@ int VideoPlayer::slotOpen(const char *videoFile, Type which) { } video->getVideo()->setVideoMemory(); - video->getVideo()->disableSound(); + video->getVideo()->enableSound(*_vm->_mixer); + + int slot = getNextFreeSlot(); - _videoSlots.push_back(video); + _videoSlots[slot] = video; WRITE_VAR(7, video->getVideo()->getFramesCount()); - return _videoSlots.size() - 1; + return slot; +} + +int VideoPlayer::getNextFreeSlot() { + uint slot; + + for (slot = 0; slot < _videoSlots.size(); slot++) + if (!_videoSlots[slot]) + break; + + if (slot == _videoSlots.size()) + _videoSlots.push_back(0); + + return slot; } void VideoPlayer::slotPlay(int slot, int16 frame) { - if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot]) return; CoktelVideo &video = *(_videoSlots[slot]->getVideo()); @@ -360,21 +387,23 @@ void VideoPlayer::slotPlay(int slot, int16 frame) { _videoSlots[slot]->nextFrame(); WRITE_VAR(11, frame); + + evalBgShading(video); } void VideoPlayer::slotClose(int slot) { - if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot]) return; delete _videoSlots[slot]; - _videoSlots.remove_at(slot); + _videoSlots[slot] = 0; } void VideoPlayer::slotCopyFrame(int slot, byte *dest, uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, uint16 pitch, int16 transp) { - if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot]) return; _videoSlots[slot]->getVideo()->copyCurrentFrame(dest, @@ -382,14 +411,24 @@ void VideoPlayer::slotCopyFrame(int slot, byte *dest, } void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) { - if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot]) return; copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd); } +void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) { + if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot]) + return; + + CoktelVideo &video = *(_videoSlots[slot]->getVideo()); + + if (!onlySound || (video.getFeatures() & CoktelVideo::kFeaturesSound)) + video.waitEndFrame(); +} + bool VideoPlayer::slotIsOpen(int slot) const { - if ((slot >= 0) && (((uint) slot) < _videoSlots.size())) + if ((slot >= 0) && (((uint) slot) < _videoSlots.size()) && _videoSlots[slot]) return true; return false; @@ -399,7 +438,7 @@ const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const { if (slot < 0) { if (_primaryVideo->isOpen()) return _primaryVideo; - } else if (((uint) slot) < _videoSlots.size()) + } else if (((uint) slot) < _videoSlots.size() && _videoSlots[slot]) return _videoSlots[slot]; return 0; @@ -503,7 +542,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, _vm->_draw->_noInvalidated = true; } - if (state.flags & CoktelVideo::kStatePalette) { + if ((state.flags & CoktelVideo::kStatePalette) && (palCmd > 1)) { copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd); if (!_backSurf) @@ -563,14 +602,13 @@ void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY, if (primaryOpen(videoFile)) { int16 x, y, width, height; - if ((VAR_OFFSET(varX) != 0xFFFFFFFF) || - !_primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height)) { + x = _primaryVideo->getVideo()->getX(); + y = _primaryVideo->getVideo()->getY(); + width = _primaryVideo->getVideo()->getWidth(); + height = _primaryVideo->getVideo()->getHeight(); - x = _primaryVideo->getVideo()->getX(); - y = _primaryVideo->getVideo()->getY(); - width = _primaryVideo->getVideo()->getWidth(); - height = _primaryVideo->getVideo()->getHeight(); - } + if (VAR_OFFSET(varX) == 0xFFFFFFFF) + _primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height); WRITE_VAR_OFFSET(varX, x); WRITE_VAR_OFFSET(varY, y); @@ -580,12 +618,28 @@ void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY, primaryClose(); } else { - WRITE_VAR_OFFSET(varX, -1); - WRITE_VAR_OFFSET(varY, -1); - WRITE_VAR_OFFSET(varFrames, -1); - WRITE_VAR_OFFSET(varWidth, -1); - WRITE_VAR_OFFSET(varHeight, -1); + WRITE_VAR_OFFSET(varX, (uint32) -1); + WRITE_VAR_OFFSET(varY, (uint32) -1); + WRITE_VAR_OFFSET(varFrames, (uint32) -1); + WRITE_VAR_OFFSET(varWidth, (uint32) -1); + WRITE_VAR_OFFSET(varHeight, (uint32) -1); } } +void VideoPlayer::evalBgShading(CoktelVideo &video) { + if (video.isSoundPlaying()) + _vm->_sound->bgShade(); + else + _vm->_sound->bgUnshade(); +} + +void VideoPlayer::notifyPaused(uint32 duration) { + if (_primaryVideo->isOpen()) + _primaryVideo->getVideo()->notifyPaused(duration); + + for (uint i = 0; i < _videoSlots.size(); i++) + if (_videoSlots[i] && _videoSlots[i]->isOpen()) + _videoSlots[i]->getVideo()->notifyPaused(duration); +} + } // End of namespace Gob diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index fd3c68aa1a..b7aa7313b0 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -68,6 +68,7 @@ public: uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, uint16 pitch, int16 transp = -1); void slotCopyPalette(int slot, int16 palStart = -1, int16 palEnd = -1); + void slotWaitEndFrame(int slot, bool onlySound = false); bool slotIsOpen(int slot) const; @@ -82,6 +83,8 @@ public: void writeVideoInfo(const char *videoFile, int16 varX, int16 varY, int16 varFrames, int16 varWidth, int16 varHeight); + void notifyPaused(uint32 duration); + private: class Video { public: @@ -127,10 +130,13 @@ private: const Video *getVideoBySlot(int slot = -1) const; + int getNextFreeSlot(); + void copyPalette(CoktelVideo &video, int16 palStart = -1, int16 palEnd = -1); bool doPlay(int16 frame, int16 breakKey, uint16 palCmd, int16 palStart, int16 palEnd, int16 palFrame, int16 endFrame); + void evalBgShading(CoktelVideo &video); }; } // End of namespace Gob diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp index 9314f8604e..c5d44d10af 100644 --- a/engines/kyra/animator_hof.cpp +++ b/engines/kyra/animator_hof.cpp @@ -127,19 +127,15 @@ void KyraEngine_HoF::updateItemAnimations() { return; const ItemAnimData_v2 *s = &_itemAnimData[_nextAnimItem]; - ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem]; - - if (++_nextAnimItem == 14) { - _nextAnimItem = 0; - return; - } + ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem]; + _nextAnimItem = ++_nextAnimItem % _itemAnimDataSize; uint32 ctime = _system->getMillis(); if (ctime < a->nextFrame) return; uint16 shpIdx = s->frames[a->currentFrame].index + 64; - if ((s->itemIndex == _handItemSet || s->itemIndex == _itemInHand) && (!_mouseState && _screen->isMouseVisible())) { + if (s->itemIndex == _mouseState && s->itemIndex == _itemInHand && _screen->isMouseVisible()) { nextFrame = true; _screen->setMouseCursor(8, 15, getShapePtr(shpIdx)); } diff --git a/engines/kyra/animator_v1.cpp b/engines/kyra/animator_lok.cpp index ea56efd9fb..1baa78b203 100644 --- a/engines/kyra/animator_v1.cpp +++ b/engines/kyra/animator_lok.cpp @@ -25,15 +25,15 @@ #include "common/endian.h" -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/screen.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" #include "kyra/sprites.h" #include "common/system.h" namespace Kyra { -Animator_v1::Animator_v1(KyraEngine_v1 *vm, OSystem *system) { +Animator_LoK::Animator_LoK(KyraEngine_LoK *vm, OSystem *system) { _vm = vm; _screen = vm->screen(); _initOk = false; @@ -48,14 +48,14 @@ Animator_v1::Animator_v1(KyraEngine_v1 *vm, OSystem *system) { memset(_actorBkgBackUp[1], 0, _screen->getRectSize(8, 69)); } -Animator_v1::~Animator_v1() { +Animator_LoK::~Animator_LoK() { close(); - delete [] _actorBkgBackUp[0]; - delete [] _actorBkgBackUp[1]; + delete[] _actorBkgBackUp[0]; + delete[] _actorBkgBackUp[1]; } -void Animator_v1::init(int actors_, int items_, int sprites_) { - debugC(9, kDebugLevelAnimator, "Animator_v1::init(%d, %d, %d)", actors_, items_, sprites_); +void Animator_LoK::init(int actors_, int items_, int sprites_) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::init(%d, %d, %d)", actors_, items_, sprites_); _screenObjects = new AnimObject[actors_ + items_ + sprites_]; assert(_screenObjects); memset(_screenObjects, 0, sizeof(AnimObject) * (actors_ + items_ + sprites_)); @@ -67,16 +67,16 @@ void Animator_v1::init(int actors_, int items_, int sprites_) { _initOk = true; } -void Animator_v1::close() { - debugC(9, kDebugLevelAnimator, "Animator_v1::close()"); +void Animator_LoK::close() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::close()"); if (_initOk) { _initOk = false; - delete [] _screenObjects; + delete[] _screenObjects; _screenObjects = _actors = _items = _sprites = _objectQueue = 0; } } -void Animator_v1::initAnimStateList() { +void Animator_LoK::initAnimStateList() { AnimObject *animStates = _screenObjects; animStates[0].index = 0; animStates[0].active = 1; @@ -118,8 +118,8 @@ void Animator_v1::initAnimStateList() { } } -void Animator_v1::preserveAllBackgrounds() { - debugC(9, kDebugLevelAnimator, "Animator_v1::preserveAllBackgrounds()"); +void Animator_LoK::preserveAllBackgrounds() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::preserveAllBackgrounds()"); uint8 curPage = _screen->_curPage; _screen->_curPage = 2; @@ -134,8 +134,8 @@ void Animator_v1::preserveAllBackgrounds() { _screen->_curPage = curPage; } -void Animator_v1::flagAllObjectsForBkgdChange() { - debugC(9, kDebugLevelAnimator, "Animator_v1::flagAllObjectsForBkgdChange()"); +void Animator_LoK::flagAllObjectsForBkgdChange() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::flagAllObjectsForBkgdChange()"); AnimObject *curObject = _objectQueue; while (curObject) { curObject->bkgdChangeFlag = 1; @@ -143,8 +143,8 @@ void Animator_v1::flagAllObjectsForBkgdChange() { } } -void Animator_v1::flagAllObjectsForRefresh() { - debugC(9, kDebugLevelAnimator, "Animator_v1::flagAllObjectsForRefresh()"); +void Animator_LoK::flagAllObjectsForRefresh() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::flagAllObjectsForRefresh()"); AnimObject *curObject = _objectQueue; while (curObject) { curObject->refreshFlag = 1; @@ -152,8 +152,8 @@ void Animator_v1::flagAllObjectsForRefresh() { } } -void Animator_v1::restoreAllObjectBackgrounds() { - debugC(9, kDebugLevelAnimator, "Animator_v1::restoreAllObjectBackground()"); +void Animator_LoK::restoreAllObjectBackgrounds() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::restoreAllObjectBackground()"); AnimObject *curObject = _objectQueue; _screen->_curPage = 2; @@ -169,8 +169,8 @@ void Animator_v1::restoreAllObjectBackgrounds() { _screen->_curPage = 0; } -void Animator_v1::preserveAnyChangedBackgrounds() { - debugC(9, kDebugLevelAnimator, "Animator_v1::preserveAnyChangedBackgrounds()"); +void Animator_LoK::preserveAnyChangedBackgrounds() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::preserveAnyChangedBackgrounds()"); AnimObject *curObject = _objectQueue; _screen->_curPage = 2; @@ -185,8 +185,8 @@ void Animator_v1::preserveAnyChangedBackgrounds() { _screen->_curPage = 0; } -void Animator_v1::preserveOrRestoreBackground(AnimObject *obj, bool restore) { - debugC(9, kDebugLevelAnimator, "Animator_v1::preserveOrRestoreBackground(%p, %d)", (const void *)obj, restore); +void Animator_LoK::preserveOrRestoreBackground(AnimObject *obj, bool restore) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::preserveOrRestoreBackground(%p, %d)", (const void *)obj, restore); int x = 0, y = 0, width = obj->width, height = obj->height; if (restore) { @@ -217,8 +217,8 @@ void Animator_v1::preserveOrRestoreBackground(AnimObject *obj, bool restore) { _screen->copyRegionToBuffer(_screen->_curPage, x << 3, y, width << 3, height, obj->background); } -void Animator_v1::prepDrawAllObjects() { - debugC(9, kDebugLevelAnimator, "Animator_v1::prepDrawAllObjects()"); +void Animator_LoK::prepDrawAllObjects() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::prepDrawAllObjects()"); AnimObject *curObject = _objectQueue; int drawPage = 2; int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0; @@ -363,8 +363,8 @@ void Animator_v1::prepDrawAllObjects() { } } -void Animator_v1::copyChangedObjectsForward(int refreshFlag) { - debugC(9, kDebugLevelAnimator, "Animator_v1::copyChangedObjectsForward(%d)", refreshFlag); +void Animator_LoK::copyChangedObjectsForward(int refreshFlag) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::copyChangedObjectsForward(%d)", refreshFlag); for (AnimObject *curObject = _objectQueue; curObject; curObject = curObject->nextAnimObject) { if (curObject->active) { @@ -404,16 +404,16 @@ void Animator_v1::copyChangedObjectsForward(int refreshFlag) { } } -void Animator_v1::updateAllObjectShapes() { - debugC(9, kDebugLevelAnimator, "Animator_v1::updateAllObjectShapes()"); +void Animator_LoK::updateAllObjectShapes() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::updateAllObjectShapes()"); restoreAllObjectBackgrounds(); preserveAnyChangedBackgrounds(); prepDrawAllObjects(); copyChangedObjectsForward(0); } -void Animator_v1::animRemoveGameItem(int index) { - debugC(9, kDebugLevelAnimator, "Animator_v1::animRemoveGameItem(%d)", index); +void Animator_LoK::animRemoveGameItem(int index) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::animRemoveGameItem(%d)", index); restoreAllObjectBackgrounds(); AnimObject *animObj = &_items[index]; @@ -427,8 +427,8 @@ void Animator_v1::animRemoveGameItem(int index) { objectRemoveQueue(_objectQueue, animObj); } -void Animator_v1::animAddGameItem(int index, uint16 sceneId) { - debugC(9, kDebugLevelAnimator, "Animator_v1::animRemoveGameItem(%d, %d)", index, sceneId); +void Animator_LoK::animAddGameItem(int index, uint16 sceneId) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::animRemoveGameItem(%d, %d)", index, sceneId); restoreAllObjectBackgrounds(); assert(sceneId < _vm->_roomTableSize); Room *currentRoom = &_vm->_roomTable[sceneId]; @@ -453,8 +453,8 @@ void Animator_v1::animAddGameItem(int index, uint16 sceneId) { animObj->bkgdChangeFlag = 1; } -void Animator_v1::animAddNPC(int character) { - debugC(9, kDebugLevelAnimator, "Animator_v1::animAddNPC(%d)", character); +void Animator_LoK::animAddNPC(int character) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::animAddNPC(%d)", character); restoreAllObjectBackgrounds(); AnimObject *animObj = &_actors[character]; const Character *ch = &_vm->_characterList[character]; @@ -478,8 +478,8 @@ void Animator_v1::animAddNPC(int character) { animObj->bkgdChangeFlag = 1; } -Animator_v1::AnimObject *Animator_v1::objectRemoveQueue(AnimObject *queue, AnimObject *rem) { - debugC(9, kDebugLevelAnimator, "Animator_v1::objectRemoveQueue(%p, %p)", (const void *)queue, (const void *)rem); +Animator_LoK::AnimObject *Animator_LoK::objectRemoveQueue(AnimObject *queue, AnimObject *rem) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::objectRemoveQueue(%p, %p)", (const void *)queue, (const void *)rem); AnimObject *cur = queue; AnimObject *prev = queue; @@ -512,14 +512,14 @@ Animator_v1::AnimObject *Animator_v1::objectRemoveQueue(AnimObject *queue, AnimO return queue; } -Animator_v1::AnimObject *Animator_v1::objectAddHead(AnimObject *queue, AnimObject *head) { - debugC(9, kDebugLevelAnimator, "Animator_v1::objectAddHead(%p, %p)", (const void *)queue, (const void *)head); +Animator_LoK::AnimObject *Animator_LoK::objectAddHead(AnimObject *queue, AnimObject *head) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::objectAddHead(%p, %p)", (const void *)queue, (const void *)head); head->nextAnimObject = queue; return head; } -Animator_v1::AnimObject *Animator_v1::objectQueue(AnimObject *queue, AnimObject *add) { - debugC(9, kDebugLevelAnimator, "Animator_v1::objectQueue(%p, %p)", (const void *)queue, (const void *)add); +Animator_LoK::AnimObject *Animator_LoK::objectQueue(AnimObject *queue, AnimObject *add) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::objectQueue(%p, %p)", (const void *)queue, (const void *)add); if (add->drawY <= queue->drawY || !queue) { add->nextAnimObject = queue; return add; @@ -544,16 +544,16 @@ Animator_v1::AnimObject *Animator_v1::objectQueue(AnimObject *queue, AnimObject return queue; } -void Animator_v1::addObjectToQueue(AnimObject *object) { - debugC(9, kDebugLevelAnimator, "Animator_v1::addObjectToQueue(%p)", (const void *)object); +void Animator_LoK::addObjectToQueue(AnimObject *object) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::addObjectToQueue(%p)", (const void *)object); if (!_objectQueue) _objectQueue = objectAddHead(0, object); else _objectQueue = objectQueue(_objectQueue, object); } -void Animator_v1::refreshObject(AnimObject *object) { - debugC(9, kDebugLevelAnimator, "Animator_v1::refreshObject(%p)", (const void *)object); +void Animator_LoK::refreshObject(AnimObject *object) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::refreshObject(%p)", (const void *)object); _objectQueue = objectRemoveQueue(_objectQueue, object); if (_objectQueue) _objectQueue = objectQueue(_objectQueue, object); @@ -561,8 +561,8 @@ void Animator_v1::refreshObject(AnimObject *object) { _objectQueue = objectAddHead(0, object); } -void Animator_v1::makeBrandonFaceMouse() { - debugC(9, kDebugLevelAnimator, "Animator_v1::makeBrandonFaceMouse()"); +void Animator_LoK::makeBrandonFaceMouse() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::makeBrandonFaceMouse()"); Common::Point mouse = _vm->getMousePos(); if (mouse.x >= _vm->_currentCharacter->x1) _vm->_currentCharacter->facing = 3; @@ -572,22 +572,22 @@ void Animator_v1::makeBrandonFaceMouse() { updateAllObjectShapes(); } -int16 Animator_v1::fetchAnimWidth(const uint8 *shape, int16 mult) { - debugC(9, kDebugLevelAnimator, "Animator_v1::fetchAnimWidth(%p, %d)", (const void *)shape, mult); +int16 Animator_LoK::fetchAnimWidth(const uint8 *shape, int16 mult) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::fetchAnimWidth(%p, %d)", (const void *)shape, mult); if (_vm->gameFlags().useAltShapeHeader) shape += 2; return (((int16)READ_LE_UINT16((shape+3))) * mult) >> 8; } -int16 Animator_v1::fetchAnimHeight(const uint8 *shape, int16 mult) { - debugC(9, kDebugLevelAnimator, "Animator_v1::fetchAnimHeight(%p, %d)", (const void *)shape, mult); +int16 Animator_LoK::fetchAnimHeight(const uint8 *shape, int16 mult) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::fetchAnimHeight(%p, %d)", (const void *)shape, mult); if (_vm->gameFlags().useAltShapeHeader) shape += 2; return (int16)(((int8)*(shape+2)) * mult) >> 8; } -void Animator_v1::setBrandonAnimSeqSize(int width, int height) { - debugC(9, kDebugLevelAnimator, "Animator_v1::setBrandonAnimSeqSize(%d, %d)", width, height); +void Animator_LoK::setBrandonAnimSeqSize(int width, int height) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::setBrandonAnimSeqSize(%d, %d)", width, height); restoreAllObjectBackgrounds(); _brandonAnimSeqSizeWidth = _actors[0].width; _brandonAnimSeqSizeHeight = _actors[0].height; @@ -596,16 +596,16 @@ void Animator_v1::setBrandonAnimSeqSize(int width, int height) { preserveAllBackgrounds(); } -void Animator_v1::resetBrandonAnimSeqSize() { - debugC(9, kDebugLevelAnimator, "Animator_v1::resetBrandonAnimSeqSize()"); +void Animator_LoK::resetBrandonAnimSeqSize() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::resetBrandonAnimSeqSize()"); restoreAllObjectBackgrounds(); _actors[0].width = _brandonAnimSeqSizeWidth; _actors[0].height = _brandonAnimSeqSizeHeight; preserveAllBackgrounds(); } -void Animator_v1::animRefreshNPC(int character) { - debugC(9, kDebugLevelAnimator, "Animator_v1::animRefreshNPC(%d)", character); +void Animator_LoK::animRefreshNPC(int character) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::animRefreshNPC(%d)", character); AnimObject *animObj = &_actors[character]; Character *ch = &_vm->characterList()[character]; @@ -663,8 +663,8 @@ void Animator_v1::animRefreshNPC(int character) { refreshObject(animObj); } -void Animator_v1::setCharacterDefaultFrame(int character) { - debugC(9, kDebugLevelAnimator, "Animator_v1::setCharacterDefaultFrame()"); +void Animator_LoK::setCharacterDefaultFrame(int character) { + debugC(9, kDebugLevelAnimator, "Animator_LoK::setCharacterDefaultFrame()"); static uint16 initFrameTable[] = { 7, 41, 77, 0, 0 }; @@ -676,8 +676,8 @@ void Animator_v1::setCharacterDefaultFrame(int character) { // edit->unk6 = 1; } -void Animator_v1::setCharactersHeight() { - debugC(9, kDebugLevelAnimator, "Animator_v1::setCharactersHeight()"); +void Animator_LoK::setCharactersHeight() { + debugC(9, kDebugLevelAnimator, "Animator_LoK::setCharactersHeight()"); static int8 initHeightTable[] = { 48, 40, 48, 47, 56, 44, 42, 47, 38, 35, diff --git a/engines/kyra/animator_v1.h b/engines/kyra/animator_lok.h index 3ae0b23da4..ba5882c710 100644 --- a/engines/kyra/animator_v1.h +++ b/engines/kyra/animator_lok.h @@ -23,14 +23,14 @@ * */ -#ifndef KYRA_ANIMATOR_V1_H -#define KYRA_ANIMATOR_V1_H +#ifndef KYRA_ANIMATOR_LOK_H +#define KYRA_ANIMATOR_LOK_H namespace Kyra { -class KyraEngine_v1; +class KyraEngine_LoK; class Screen; -class Animator_v1 { +class Animator_LoK { public: struct AnimObject { uint8 index; @@ -53,8 +53,8 @@ public: AnimObject *nextAnimObject; }; - Animator_v1(KyraEngine_v1 *vm, OSystem *system); - virtual ~Animator_v1(); + Animator_LoK(KyraEngine_LoK *vm, OSystem *system); + virtual ~Animator_LoK(); operator bool() const { return _initOk; } @@ -101,7 +101,7 @@ public: int _brandonScaleY; protected: - KyraEngine_v1 *_vm; + KyraEngine_LoK *_vm; Screen *_screen; OSystem *_system; bool _initOk; diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp index ab3d347549..9702499fe7 100644 --- a/engines/kyra/animator_mr.cpp +++ b/engines/kyra/animator_mr.cpp @@ -196,6 +196,58 @@ void KyraEngine_MR::refreshAnimObjects(int force) { } } +void KyraEngine_MR::updateItemAnimations() { + debugC(9, kDebugLevelAnimator, "KyraEngine_MR::updateItemAnimations()"); + bool nextFrame = false; + + if (_itemAnimData[0].itemIndex == -1) + return; + + const ItemAnimData_v2 *s = &_itemAnimData[_nextAnimItem]; + ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem]; + _nextAnimItem = ++_nextAnimItem % 10; + + uint32 ctime = _system->getMillis(); + if (ctime < a->nextFrame) + return; + + uint16 shpIdx = s->frames[a->currentFrame].index + 248; + if (s->itemIndex == _mouseState && s->itemIndex == _itemInHand && _screen->isMouseVisible()) { + nextFrame = true; + _screen->setMouseCursor(12, 19, getShapePtr(shpIdx)); + } + + if (_inventoryState) { + for (int i = 0; i < 10; i++) { + if (s->itemIndex == _mainCharacter.inventory[i]) { + nextFrame = true; + _screen->drawShape(2, getShapePtr(422 + i), 9, 0, 0, 0); + _screen->drawShape(2, getShapePtr(shpIdx), 9, 0, 0, 0); + _screen->hideMouse(); + _screen->copyRegion(9, 0, _inventoryX[i], _inventoryY[i], 24, 20, 2, 0, Screen::CR_NO_P_CHECK); + _screen->showMouse(); + } + } + } + + _screen->updateScreen(); + + for (int i = 17; i < 66; i++) { + AnimObj *animObject = &_animObjects[i]; + if (animObject->shapeIndex2 == s->itemIndex + 248) { + animObject->shapePtr = getShapePtr(shpIdx); + animObject->shapeIndex1 = shpIdx; + animObject->needRefresh = true; + nextFrame = true; + } + } + + if (nextFrame) { + a->nextFrame = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength); + a->currentFrame = ++a->currentFrame % s->numFrames; + } +} + void KyraEngine_MR::updateCharacterAnim(int charId) { debugC(9, kDebugLevelAnimator, "KyraEngine_MR::updateCharacterAnim(%d)", charId); diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index 51e4d17487..7ae5414d82 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -27,7 +27,7 @@ #include "common/config-manager.h" #include "common/system.h" #include "kyra/debugger.h" -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/kyra_v2.h" #include "kyra/kyra_hof.h" #include "kyra/screen.h" @@ -36,7 +36,7 @@ namespace Kyra { -Debugger::Debugger(KyraEngine *vm) +Debugger::Debugger(KyraEngine_v1 *vm) : ::GUI::Debugger() { _vm = vm; @@ -190,22 +190,23 @@ bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { #pragma mark - -Debugger_v1::Debugger_v1(KyraEngine_v1 *vm) +Debugger_LoK::Debugger_LoK(KyraEngine_LoK *vm) : Debugger(vm), _vm(vm) { - DCmd_Register("rooms", WRAP_METHOD(Debugger_v1, cmd_listRooms)); - DCmd_Register("give", WRAP_METHOD(Debugger_v1, cmd_giveItem)); - DCmd_Register("birthstones", WRAP_METHOD(Debugger_v1, cmd_listBirthstones)); + DCmd_Register("enter", WRAP_METHOD(Debugger_LoK, cmd_enterRoom)); + DCmd_Register("rooms", WRAP_METHOD(Debugger_LoK, cmd_listRooms)); + DCmd_Register("give", WRAP_METHOD(Debugger_LoK, cmd_giveItem)); + DCmd_Register("birthstones", WRAP_METHOD(Debugger_LoK, cmd_listBirthstones)); } -void Debugger_v1::preEnter() { +void Debugger_LoK::preEnter() { //_vm->midi.pause(1); } -void Debugger_v1::postEnter() { +void Debugger_LoK::postEnter() { //_vm->midi.pause(0); } -bool Debugger_v1::cmd_enterRoom(int argc, const char **argv) { +bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) { uint direction = 0; if (argc > 1) { int room = atoi(argv[1]); @@ -244,7 +245,7 @@ bool Debugger_v1::cmd_enterRoom(int argc, const char **argv) { return true; } -bool Debugger_v1::cmd_listRooms(int argc, const char **argv) { +bool Debugger_LoK::cmd_listRooms(int argc, const char **argv) { for (int i = 0; i < _vm->_roomTableSize; i++) { DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); if (!(i % 8)) @@ -255,7 +256,7 @@ bool Debugger_v1::cmd_listRooms(int argc, const char **argv) { return true; } -bool Debugger_v1::cmd_giveItem(int argc, const char **argv) { +bool Debugger_LoK::cmd_giveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); @@ -274,7 +275,7 @@ bool Debugger_v1::cmd_giveItem(int argc, const char **argv) { return true; } -bool Debugger_v1::cmd_listBirthstones(int argc, const char **argv) { +bool Debugger_LoK::cmd_listBirthstones(int argc, const char **argv) { DebugPrintf("Needed Birthstone gems:\n"); for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i) DebugPrintf("%-2d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]); @@ -421,9 +422,8 @@ bool Debugger_v2::cmd_giveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); - // Kyrandia 2 has only 178 items (-1 to 176), otherwise it will crash - if (item < -1 || item > 176) { - DebugPrintf("itemid must be any value between (including) -1 and 176\n"); + if (item < -1 || item > _vm->engineDesc().maxItemId) { + DebugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId); return true; } diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index ab5657bbde..7cdfa26e93 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -30,18 +30,18 @@ namespace Kyra { -class KyraEngine; class KyraEngine_v1; +class KyraEngine_LoK; class KyraEngine_v2; class KyraEngine_HoF; class Debugger : public ::GUI::Debugger { public: - Debugger(KyraEngine *vm); + Debugger(KyraEngine_v1 *vm); virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; bool cmd_setScreenDebug(int argc, const char **argv); bool cmd_loadPalette(int argc, const char **argv); @@ -54,13 +54,13 @@ protected: bool cmd_setTimerCountdown(int argc, const char **argv); }; -class Debugger_v1 : public Debugger { +class Debugger_LoK : public Debugger { public: - Debugger_v1(KyraEngine_v1 *vm); - virtual ~Debugger_v1() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ + Debugger_LoK(KyraEngine_LoK *vm); + virtual ~Debugger_LoK() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ protected: - KyraEngine_v1 *_vm; + KyraEngine_LoK *_vm; virtual void preEnter(); virtual void postEnter(); diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index b921314e68..344121b503 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -22,8 +22,8 @@ * $Id$ */ -#include "kyra/kyra.h" #include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/kyra_hof.h" #include "kyra/kyra_mr.h" @@ -41,22 +41,25 @@ struct KYRAGameDescription { namespace { -#define FLAGS(x, y, z, a, b, id) { Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, id } +#define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id } -#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, Kyra::GI_KYRA1) -#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, Kyra::GI_KYRA1) +#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, Kyra::GI_KYRA2) -#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, Kyra::GI_KYRA2) +#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA2) +#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_KYRA2) -#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, Kyra::GI_KYRA3) +#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3) +#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3) const KYRAGameDescription adGameDescs[] = { { @@ -279,7 +282,7 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), Common::IT_ITA, Common::kPlatformPC, - Common::ADGF_NO_FLAGS + Common::ADGF_CD }, KYRA1_CD_FLAGS }, @@ -296,6 +299,66 @@ const KYRAGameDescription adGameDescs[] = { KYRA1_DEMO_FLAGS }, + { // Floppy version + { + "kyra2", + 0, + AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA2_FLOPPY_CMP_FLAGS + }, + + { // Floppy version + { + "kyra2", + 0, + AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA2_FLOPPY_CMP_FLAGS + }, + + { // // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"), + Common::FR_FRA, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + KYRA2_FLOPPY_FLAGS + }, + { // CD version { "kyra2", @@ -401,11 +464,65 @@ const KYRAGameDescription adGameDescs[] = { KYRA2_TOWNS_SJIS_FLAGS }, + // Kyra3 + + // non installed version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_INS_FLAGS + }, { { "kyra3", 0, - AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + Common::ADGF_DROPLANGUAGE + }, + KYRA3_CD_INS_FLAGS + }, + + // installed version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, Common::EN_ANY, Common::kPlatformPC, Common::ADGF_DROPLANGUAGE @@ -416,7 +533,11 @@ const KYRAGameDescription adGameDescs[] = { { "kyra3", 0, - AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, Common::DE_DEU, Common::kPlatformPC, Common::ADGF_DROPLANGUAGE @@ -427,7 +548,11 @@ const KYRAGameDescription adGameDescs[] = { { "kyra3", 0, - AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, Common::FR_FRA, Common::kPlatformPC, Common::ADGF_DROPLANGUAGE @@ -435,7 +560,7 @@ const KYRAGameDescription adGameDescs[] = { KYRA3_CD_FLAGS }, - { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0) } + { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) } }; const PlainGameDescriptor gameList[] = { @@ -506,7 +631,7 @@ bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common switch (flags.gameID) { case Kyra::GI_KYRA1: - *engine = new Kyra::KyraEngine_v1(syst, flags); + *engine = new Kyra::KyraEngine_LoK(syst, flags); break; case Kyra::GI_KYRA2: *engine = new Kyra::KyraEngine_HoF(syst, flags); @@ -524,7 +649,7 @@ bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common SaveStateList KyraMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - Kyra::KyraEngine::SaveHeader header; + Kyra::KyraEngine_v1::SaveHeader header; Common::String pattern = target; pattern += ".???"; @@ -540,7 +665,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const { if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { - if (Kyra::KyraEngine::readSaveHeader(in, header) == Kyra::KyraEngine::kRSHENoError) + if (Kyra::KyraEngine_v1::readSaveHeader(in, header) == Kyra::KyraEngine_v1::kRSHENoError) saveList.push_back(SaveStateDescriptor(slotNum, header.description, *file)); delete in; } diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index d2e02671c9..96ea233025 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -33,10 +33,9 @@ namespace Kyra { -GUI::GUI(KyraEngine *kyra) +GUI::GUI(KyraEngine_v1 *kyra) : _vm(kyra), _screen(kyra->screen()), _text(kyra->text()) { _menuButtonList = 0; - _haveScrollButtons = false; _redrawButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawButtonCallback); _redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawShadedButtonCallback); @@ -148,13 +147,12 @@ void GUI::initMenu(Menu &menu) { } if (menu.scrollUpButtonX != -1) { - _haveScrollButtons = true; - Button *scrollUpButton = getScrollUpButton(); scrollUpButton->x = menu.scrollUpButtonX + menu.x; scrollUpButton->y = menu.scrollUpButtonY + menu.y; scrollUpButton->buttonCallback = getScrollUpButtonHandler(); scrollUpButton->nextButton = 0; + scrollUpButton->mouseWheel = -1; _menuButtonList = addButtonToList(_menuButtonList, scrollUpButton); updateMenuButton(scrollUpButton); @@ -164,11 +162,10 @@ void GUI::initMenu(Menu &menu) { scrollDownButton->y = menu.scrollDownButtonY + menu.y; scrollDownButton->buttonCallback = getScrollDownButtonHandler(); scrollDownButton->nextButton = 0; + scrollDownButton->mouseWheel = 1; _menuButtonList = addButtonToList(_menuButtonList, scrollDownButton); updateMenuButton(scrollDownButton); - } else { - _haveScrollButtons = false; } _screen->showMouse(); @@ -342,7 +339,7 @@ int GUI::getNextSavegameSlot() { #pragma mark - -MainMenu::MainMenu(KyraEngine *vm) : _vm(vm), _screen(0) { +MainMenu::MainMenu(KyraEngine_v1 *vm) : _vm(vm), _screen(0) { _screen = _vm->screen(); _nextUpdate = 0; _system = g_system; @@ -382,7 +379,7 @@ bool MainMenu::getInput() { while (_system->getEventManager()->pollEvent(event)) { switch (event.type) { case Common::EVENT_QUIT: - _quitFlag = true; + _vm->quitGame(); break; case Common::EVENT_LBUTTONUP: return true; @@ -396,7 +393,6 @@ bool MainMenu::getInput() { int MainMenu::handle(int dim) { debugC(9, kDebugLevelMain, "MainMenu::handle(%d)", dim); int command = -1; - _quitFlag = false; uint8 colorMap[16]; memset(colorMap, 0, sizeof(colorMap)); @@ -436,7 +432,7 @@ int MainMenu::handle(int dim) { Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4); - while (!_quitFlag) { + while (!_vm->quit()) { updateAnimation(); bool mousePressed = getInput(); @@ -467,7 +463,7 @@ int MainMenu::handle(int dim) { _system->delayMillis(10); } - if (_quitFlag) + if (_vm->quit()) command = -1; _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0); diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h index a04ac20de3..1361bdb399 100644 --- a/engines/kyra/gui.h +++ b/engines/kyra/gui.h @@ -26,7 +26,7 @@ #ifndef KYRA_GUI_H #define KYRA_GUI_H -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "common/ptr.h" #include "common/array.h" @@ -75,6 +75,8 @@ struct Button { uint16 flags2; + int8 mouseWheel; + Callback buttonCallback; }; @@ -133,14 +135,14 @@ class TextDisplayer; class GUI { public: - GUI(KyraEngine *vm); + GUI(KyraEngine_v1 *vm); virtual ~GUI() {} // button specific virtual Button *addButtonToList(Button *list, Button *newButton); virtual void processButton(Button *button) = 0; - virtual int processButtonList(Button *buttonList, uint16 inputFlags) = 0; + virtual int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel) = 0; virtual int redrawShadedButtonCallback(Button *button); virtual int redrawButtonCallback(Button *button); @@ -152,12 +154,11 @@ public: void processHighlights(Menu &menu, int mouseX, int mouseY); protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; Screen *_screen; TextDisplayer *_text; Button *_menuButtonList; - bool _haveScrollButtons; bool _displayMenu; bool _displaySubMenu; bool _cancelSubMenu; @@ -195,7 +196,7 @@ class Movie; class MainMenu { public: - MainMenu(KyraEngine *vm); + MainMenu(KyraEngine_v1 *vm); virtual ~MainMenu() {} struct Animation { @@ -218,12 +219,10 @@ public: void init(StaticData data, Animation anim); int handle(int dim); private: - KyraEngine *_vm; + KyraEngine_v1 *_vm; Screen *_screen; OSystem *_system; - bool _quitFlag; - StaticData _static; struct AnimIntern { int curFrame; diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index d1fcaa4712..555934cb7f 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -23,7 +23,7 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_hof.h" #include "kyra/screen.h" #include "kyra/wsamovie.h" @@ -271,7 +271,7 @@ void KyraEngine_HoF::redrawInventory(int page) { } void KyraEngine_HoF::scrollInventoryWheel() { - WSAMovieV2 movie(this, _screen); + WSAMovie_v2 movie(this, _screen); movie.open("INVWHEEL.WSA", 0, 0); int frames = movie.opened() ? movie.frames() : 6; memcpy(_screenBuffer, _screen->getCPagePtr(2), 64000); @@ -348,7 +348,7 @@ int KyraEngine_HoF::bookButton(Button *button) { return 0; } - if (_handItemSet != -1) { + if (_mouseState != -1) { snd_playSoundEffect(0x0D); return 0; } @@ -455,12 +455,12 @@ void KyraEngine_HoF::showBookPage() { char filename[16]; sprintf(filename, "PAGE%.01X.", _bookCurPage); - strcat(filename, _languageExtension[_lang]); + strcat(filename, (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _lang) ? _languageExtension[_lang] : "TXT"); uint8 *leftPage = _res->fileData(filename, 0); int leftPageY = _bookPageYOffset[_bookCurPage]; sprintf(filename, "PAGE%.01X.", _bookCurPage+1); - strcat(filename, _languageExtension[_lang]); + strcat(filename, (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _lang) ? _languageExtension[_lang] : "TXT"); uint8 *rightPage = (_bookCurPage != _bookMaxPage) ? _res->fileData(filename, 0) : 0; int rightPageY = _bookPageYOffset[_bookCurPage+1]; @@ -468,13 +468,13 @@ void KyraEngine_HoF::showBookPage() { if (leftPage) { bookDecodeText(leftPage); bookPrintText(2, leftPage, 20, leftPageY+20, 0x31); - delete [] leftPage; + delete[] leftPage; } if (rightPage) { bookDecodeText(rightPage); bookPrintText(2, rightPage, 176, rightPageY+20, 0x31); - delete [] rightPage; + delete[] rightPage; } _screen->showMouse(); } @@ -515,6 +515,7 @@ void KyraEngine_HoF::bookLoop() { _screen->updateScreen(); _screen->showMouse(); } + _system->delayMillis(10); } _screen->clearPage(2); } @@ -600,7 +601,7 @@ int KyraEngine_HoF::cauldronButton(Button *button) { return 0; } - if (!_screen->isMouseVisible() || _handItemSet < -1) + if (!_screen->isMouseVisible() || _mouseState < -1) return 0; if (queryGameFlag(0xE4)) { @@ -666,6 +667,8 @@ int KyraEngine_HoF::cauldronButton(Button *button) { #pragma mark - int GUI_HoF::optionsButton(Button *button) { + PauseTimer pause(*_vm->_timer); + _restartGame = false; _reloadTemporarySave = false; @@ -678,8 +681,8 @@ int GUI_HoF::optionsButton(Button *button) { _vm->showMessage(0, 0xCF); - if (_vm->_handItemSet < -1) { - _vm->_handItemSet = -1; + if (_vm->_mouseState < -1) { + _vm->_mouseState = -1; _screen->hideMouse(); _screen->setMouseCursor(1, 1, _vm->getShapePtr(0)); _screen->showMouse(); @@ -824,10 +827,10 @@ void GUI_HoF::drawSliderBar(int slider, const uint8 *shape) { int position = 0; if (_vm->gameFlags().isTalkie) { - position = _vm->getVolume(KyraEngine::kVolumeEntry(slider)); + position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider)); } else { if (slider < 2) - position = _vm->getVolume(KyraEngine::kVolumeEntry(slider)); + position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider)); else if (slider == 2) position = (_vm->_configWalkspeed == 3) ? 97 : 2; else if (slider == 3) @@ -897,7 +900,7 @@ int GUI_HoF::audioOptions(Button *caller) { restorePage1(_vm->_screenBuffer); backUpPage1(_vm->_screenBuffer); - if (speechEnabled && !_vm->textEnabled() && (!_vm->speechEnabled() || _vm->getVolume(KyraEngine::kVolumeSpeech) == 2)) { + if (speechEnabled && !_vm->textEnabled() && (!_vm->speechEnabled() || _vm->getVolume(KyraEngine_v1::kVolumeSpeech) == 2)) { _vm->_configVoice = 0; choiceDialog(0x1D, 0); } @@ -975,7 +978,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) { if (textEnabled && !_vm->textEnabled() && !_vm->speechEnabled()) { _vm->_configVoice = 1; - _vm->setVolume(KyraEngine::kVolumeSpeech, 75); + _vm->setVolume(KyraEngine_v1::kVolumeSpeech, 75); choiceDialog(0x1E, 0); } @@ -1051,10 +1054,10 @@ int GUI_HoF::sliderHandler(Button *caller) { int oldVolume = 0; if (_vm->gameFlags().isTalkie) { - oldVolume = _vm->getVolume(KyraEngine::kVolumeEntry(button)); + oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); } else { if (button < 2) - oldVolume = _vm->getVolume(KyraEngine::kVolumeEntry(button)); + oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); else if (button == 2) oldVolume = (_vm->_configWalkspeed == 3) ? 97 : 2; else if (button == 3) @@ -1089,7 +1092,7 @@ int GUI_HoF::sliderHandler(Button *caller) { _vm->_configVoice = 1; } - _vm->setVolume(KyraEngine::kVolumeEntry(button), newVolume); + _vm->setVolume(KyraEngine_v1::kVolumeEntry(button), newVolume); switch (button) { case 0: @@ -1109,7 +1112,7 @@ int GUI_HoF::sliderHandler(Button *caller) { } } else { if (button < 2) { - _vm->setVolume(KyraEngine::kVolumeEntry(button), newVolume); + _vm->setVolume(KyraEngine_v1::kVolumeEntry(button), newVolume); if (button == 0) lastMusicCommand = _vm->_lastMusicCommand; else @@ -1126,7 +1129,7 @@ int GUI_HoF::sliderHandler(Button *caller) { if (playSoundEffect) _vm->snd_playSoundEffect(0x18); else if (lastMusicCommand >= 0) - _vm->snd_playWanderScoreViaMap(lastMusicCommand, 1); + _vm->snd_playWanderScoreViaMap(lastMusicCommand, 0); _screen->updateScreen(); return 0; diff --git a/engines/kyra/gui_v1.cpp b/engines/kyra/gui_lok.cpp index e5a0c42281..6fa30c9e9a 100644 --- a/engines/kyra/gui_v1.cpp +++ b/engines/kyra/gui_lok.cpp @@ -23,13 +23,14 @@ * */ -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/screen.h" #include "kyra/script.h" #include "kyra/text.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" #include "kyra/sound.h" -#include "kyra/gui_v1.h" +#include "kyra/gui_lok.h" +#include "kyra/timer.h" #include "common/config-manager.h" #include "common/savefile.h" @@ -38,13 +39,13 @@ namespace Kyra { -void KyraEngine_v1::initMainButtonList() { +void KyraEngine_LoK::initMainButtonList() { _buttonList = &_buttonData[0]; for (int i = 0; _buttonDataListPtr[i]; ++i) _buttonList = _gui->addButtonToList(_buttonList, _buttonDataListPtr[i]); } -int KyraEngine_v1::buttonInventoryCallback(Button *caller) { +int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { int itemOffset = caller->index - 2; uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset]; if (_itemInHand == -1) { @@ -88,7 +89,7 @@ int KyraEngine_v1::buttonInventoryCallback(Button *caller) { return 0; } -int KyraEngine_v1::buttonAmuletCallback(Button *caller) { +int KyraEngine_LoK::buttonAmuletCallback(Button *caller) { if (!(_deathHandler & 8)) return 1; int jewel = caller->index - 0x14; @@ -186,30 +187,30 @@ int KyraEngine_v1::buttonAmuletCallback(Button *caller) { #pragma mark - -GUI_v1::GUI_v1(KyraEngine_v1 *vm, Screen_v1 *screen) : GUI(vm), _vm(vm), _screen(screen) { +GUI_LoK::GUI_LoK(KyraEngine_LoK *vm, Screen_LoK *screen) : GUI(vm), _vm(vm), _screen(screen) { _menu = 0; initStaticResource(); - _scrollUpFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::scrollUp); - _scrollDownFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::scrollDown); + _scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::scrollUp); + _scrollDownFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::scrollDown); } -GUI_v1::~GUI_v1() { - delete [] _menu; +GUI_LoK::~GUI_LoK() { + delete[] _menu; } -int GUI_v1::processButtonList(Button *list, uint16 inputFlag) { - if (_haveScrollButtons) { - if (_mouseWheel < 0) - scrollUp(&_scrollUpButton); - else if (_mouseWheel > 0) - scrollDown(&_scrollDownButton); - } +int GUI_LoK::processButtonList(Button *list, uint16 inputFlag, int8 mouseWheel) { while (list) { if (list->flags & 8) { list = list->nextButton; continue; } + if (mouseWheel && list->mouseWheel == mouseWheel && list->buttonCallback) { + if ((*list->buttonCallback.get())(list)) { + break; + } + } + int x = list->x; int y = list->y; assert(_screen->getScreenDim(list->dimTableIndex) != 0); @@ -271,7 +272,7 @@ int GUI_v1::processButtonList(Button *list, uint16 inputFlag) { return 0; } -void GUI_v1::processButton(Button *button) { +void GUI_LoK::processButton(Button *button) { if (!button) return; @@ -315,7 +316,7 @@ void GUI_v1::processButton(Button *button) { (*callback.get())(button); } -void GUI_v1::setGUILabels() { +void GUI_LoK::setGUILabels() { int offset = 0; int offsetOptions = 0; int offsetMainMenu = 0; @@ -336,6 +337,8 @@ void GUI_v1::setGUILabels() { } else if (_vm->gameFlags().lang == Common::ES_ESP) { offsetOn = offsetMainMenu = offsetOptions = offset = -4; menuLabelGarbageOffset = 72; + } else if (_vm->gameFlags().lang == Common::IT_ITA) { + offsetOn = offsetMainMenu = offsetOptions = offset = 32; } else if (_vm->gameFlags().lang == Common::DE_DEU) { offset = offsetMainMenu = offsetOn = offsetOptions = 24; } else if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) { @@ -405,7 +408,9 @@ void GUI_v1::setGUILabels() { _onCDString = _vm->_guiStrings[21]; } -int GUI_v1::buttonMenuCallback(Button *caller) { +int GUI_LoK::buttonMenuCallback(Button *caller) { + PauseTimer pause(*_vm->_timer); + _displayMenu = true; assert(_vm->_guiStrings); @@ -420,7 +425,7 @@ int GUI_v1::buttonMenuCallback(Button *caller) { */ setGUILabels(); - if (_vm->_currentCharacter->sceneId == 210 && _vm->_deathHandler == 0xFF) { + if (_vm->_currentCharacter->sceneId == 210 && _vm->_deathHandler == -1) { _vm->snd_playSoundEffect(0x36); return 0; } @@ -457,7 +462,7 @@ int GUI_v1::buttonMenuCallback(Button *caller) { while (_displayMenu && !_vm->_quitFlag) { Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[_toplevelMenu], mouse.x, mouse.y); - processButtonList(_menuButtonList, 0); + processButtonList(_menuButtonList, 0, 0); getInput(); } @@ -472,7 +477,7 @@ int GUI_v1::buttonMenuCallback(Button *caller) { return 0; } -void GUI_v1::getInput() { +void GUI_LoK::getInput() { Common::Event event; static uint32 lastScreenUpdate = 0; uint32 now = _vm->_system->getMillis(); @@ -515,15 +520,15 @@ void GUI_v1::getInput() { _vm->_system->delayMillis(3); } -int GUI_v1::resumeGame(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::resumeGame()"); +int GUI_LoK::resumeGame(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::resumeGame()"); updateMenuButton(button); _displayMenu = false; return 0; } -void GUI_v1::setupSavegames(Menu &menu, int num) { +void GUI_LoK::setupSavegames(Menu &menu, int num) { Common::InSaveFile *in; static char savenames[5][31]; uint8 startSlot; @@ -541,7 +546,7 @@ void GUI_v1::setupSavegames(Menu &menu, int num) { for (int i = startSlot; i < num; ++i) menu.item[i].enabled = 0; - KyraEngine::SaveHeader header; + KyraEngine_v1::SaveHeader header; for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); i++) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) { strncpy(savenames[i], header.description.c_str(), 31); @@ -553,8 +558,8 @@ void GUI_v1::setupSavegames(Menu &menu, int num) { } } -int GUI_v1::saveGameMenu(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::saveGameMenu()"); +int GUI_LoK::saveGameMenu(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::saveGameMenu()"); updateSaveList(); updateMenuButton(button); @@ -566,7 +571,7 @@ int GUI_v1::saveGameMenu(Button *button) { _menu[2].menuNameString = _vm->_guiStrings[8]; // Select a position to save to: _specialSavegameString = _vm->_guiStrings[9]; // [ EMPTY SLOT ] for (int i = 0; i < 5; i++) - _menu[2].item[i].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::saveGame); + _menu[2].item[i].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::saveGame); _savegameOffset = 0; setupSavegames(_menu[2], 5); @@ -581,7 +586,7 @@ int GUI_v1::saveGameMenu(Button *button) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); - processButtonList(_menuButtonList, 0); + processButtonList(_menuButtonList, 0, _mouseWheel); } _screen->loadPageFromDisk("SEENPAGE.TMP", 0); @@ -596,8 +601,8 @@ int GUI_v1::saveGameMenu(Button *button) { return 0; } -int GUI_v1::loadGameMenu(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::loadGameMenu()"); +int GUI_LoK::loadGameMenu(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::loadGameMenu()"); updateSaveList(); if (_vm->_menuDirectlyToLoad) { @@ -613,7 +618,7 @@ int GUI_v1::loadGameMenu(Button *button) { _specialSavegameString = _vm->_newGameString[0]; //[ START A NEW GAME ] _menu[2].menuNameString = _vm->_guiStrings[7]; // Which game would you like to reload? for (int i = 0; i < 5; i++) - _menu[2].item[i].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::loadGame); + _menu[2].item[i].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::loadGame); _savegameOffset = 0; setupSavegames(_menu[2], 5); @@ -630,7 +635,7 @@ int GUI_v1::loadGameMenu(Button *button) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[2], mouse.x, mouse.y); - processButtonList(_menuButtonList, 0); + processButtonList(_menuButtonList, 0, _mouseWheel); } _screen->loadPageFromDisk("SEENPAGE.TMP", 0); @@ -649,7 +654,7 @@ int GUI_v1::loadGameMenu(Button *button) { return 0; } -void GUI_v1::redrawTextfield() { +void GUI_LoK::redrawTextfield() { _screen->fillRect(38, 91, 287, 102, 250); _text->printText(_savegameName, 38, 92, 253, 0, 0); @@ -661,7 +666,7 @@ void GUI_v1::redrawTextfield() { _screen->updateScreen(); } -void GUI_v1::updateSavegameString() { +void GUI_LoK::updateSavegameString() { int length; if (_keyPressed.keycode) { @@ -688,8 +693,8 @@ void GUI_v1::updateSavegameString() { _keyPressed.reset(); } -int GUI_v1::saveGame(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::saveGame()"); +int GUI_LoK::saveGame(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::saveGame()"); updateMenuButton(button); _vm->_gameToLoad = _menu[2].item[button->index-0xC].saveSlot; @@ -719,7 +724,7 @@ int GUI_v1::saveGame(Button *button) { updateSavegameString(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[3], mouse.x, mouse.y); - processButtonList(_menuButtonList, 0); + processButtonList(_menuButtonList, 0, 0); } if (_cancelSubMenu) { @@ -737,16 +742,16 @@ int GUI_v1::saveGame(Button *button) { return 0; } -int GUI_v1::savegameConfirm(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::savegameConfirm()"); +int GUI_LoK::savegameConfirm(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::savegameConfirm()"); updateMenuButton(button); _displaySubMenu = false; return 0; } -int GUI_v1::loadGame(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::loadGame()"); +int GUI_LoK::loadGame(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::loadGame()"); updateMenuButton(button); _displaySubMenu = false; _vm->_gameToLoad = _menu[2].item[button->index-0xC].saveSlot; @@ -754,8 +759,8 @@ int GUI_v1::loadGame(Button *button) { return 0; } -int GUI_v1::cancelSubMenu(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::cancelSubMenu()"); +int GUI_LoK::cancelSubMenu(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::cancelSubMenu()"); updateMenuButton(button); _displaySubMenu = false; _cancelSubMenu = true; @@ -763,8 +768,8 @@ int GUI_v1::cancelSubMenu(Button *button) { return 0; } -int GUI_v1::quitPlaying(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::quitPlaying()"); +int GUI_LoK::quitPlaying(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::quitPlaying()"); updateMenuButton(button); if (quitConfirm(_vm->_guiStrings[14])) { // Are you sure you want to quit playing? @@ -777,8 +782,8 @@ int GUI_v1::quitPlaying(Button *button) { return 0; } -bool GUI_v1::quitConfirm(const char *str) { - debugC(9, kDebugLevelGUI, "GUI_v1::quitConfirm()"); +bool GUI_LoK::quitConfirm(const char *str) { + debugC(9, kDebugLevelGUI, "GUI_LoK::quitConfirm()"); _screen->loadPageFromDisk("SEENPAGE.TMP", 0); _screen->savePageToDisk("SEENPAGE.TMP", 0); @@ -794,7 +799,7 @@ bool GUI_v1::quitConfirm(const char *str) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[1], mouse.x, mouse.y); - processButtonList(_menuButtonList, 0); + processButtonList(_menuButtonList, 0, 0); } _screen->loadPageFromDisk("SEENPAGE.TMP", 0); @@ -803,8 +808,8 @@ bool GUI_v1::quitConfirm(const char *str) { return !_cancelSubMenu; } -int GUI_v1::quitConfirmYes(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::quitConfirmYes()"); +int GUI_LoK::quitConfirmYes(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::quitConfirmYes()"); updateMenuButton(button); _displaySubMenu = false; _cancelSubMenu = false; @@ -812,8 +817,8 @@ int GUI_v1::quitConfirmYes(Button *button) { return 0; } -int GUI_v1::quitConfirmNo(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::quitConfirmNo()"); +int GUI_LoK::quitConfirmNo(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::quitConfirmNo()"); updateMenuButton(button); _displaySubMenu = false; _cancelSubMenu = true; @@ -821,8 +826,8 @@ int GUI_v1::quitConfirmNo(Button *button) { return 0; } -int GUI_v1::gameControlsMenu(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::gameControlsMenu()"); +int GUI_LoK::gameControlsMenu(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::gameControlsMenu()"); _vm->readSettings(); @@ -839,14 +844,14 @@ int GUI_v1::gameControlsMenu(Button *button) { } _menu[5].item[3].labelString = _voiceTextString; //"Voice / Text " - _menu[5].item[3].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsChangeVoice); + _menu[5].item[3].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeVoice); } else { //_menu[5].height = 136; //_menu[5].item[5].y = 110; _menu[5].item[4].enabled = 0; _menu[5].item[3].labelString = _textSpeedString; // "Text speed " - _menu[5].item[3].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsChangeText); + _menu[5].item[3].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeText); } setupControls(_menu[5]); @@ -860,7 +865,7 @@ int GUI_v1::gameControlsMenu(Button *button) { getInput(); Common::Point mouse = _vm->getMousePos(); processHighlights(_menu[5], mouse.x, mouse.y); - processButtonList(_menuButtonList, 0); + processButtonList(_menuButtonList, 0, 0); } _screen->loadPageFromDisk("SEENPAGE.TMP", 0); @@ -873,8 +878,8 @@ int GUI_v1::gameControlsMenu(Button *button) { return 0; } -void GUI_v1::setupControls(Menu &menu) { - debugC(9, kDebugLevelGUI, "GUI_v1::setupControls()"); +void GUI_LoK::setupControls(Menu &menu) { + debugC(9, kDebugLevelGUI, "GUI_LoK::setupControls()"); switch (_vm->_configMusic) { case 0: @@ -970,8 +975,8 @@ void GUI_v1::setupControls(Menu &menu) { initMenu(menu); } -int GUI_v1::controlsChangeMusic(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::controlsChangeMusic()"); +int GUI_LoK::controlsChangeMusic(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeMusic()"); updateMenuButton(button); _vm->_configMusic = ++_vm->_configMusic % ((_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) ? 3 : 2); @@ -979,8 +984,8 @@ int GUI_v1::controlsChangeMusic(Button *button) { return 0; } -int GUI_v1::controlsChangeSounds(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::controlsChangeSounds()"); +int GUI_LoK::controlsChangeSounds(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeSounds()"); updateMenuButton(button); _vm->_configSounds = !_vm->_configSounds; @@ -988,8 +993,8 @@ int GUI_v1::controlsChangeSounds(Button *button) { return 0; } -int GUI_v1::controlsChangeWalk(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::controlsChangeWalk()"); +int GUI_LoK::controlsChangeWalk(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeWalk()"); updateMenuButton(button); _vm->_configWalkspeed = ++_vm->_configWalkspeed % 5; @@ -998,8 +1003,8 @@ int GUI_v1::controlsChangeWalk(Button *button) { return 0; } -int GUI_v1::controlsChangeText(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::controlsChangeText()"); +int GUI_LoK::controlsChangeText(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeText()"); updateMenuButton(button); _vm->_configTextspeed = ++_vm->_configTextspeed % 4; @@ -1007,8 +1012,8 @@ int GUI_v1::controlsChangeText(Button *button) { return 0; } -int GUI_v1::controlsChangeVoice(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::controlsChangeVoice()"); +int GUI_LoK::controlsChangeVoice(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeVoice()"); updateMenuButton(button); _vm->_configVoice = ++_vm->_configVoice % 3; @@ -1016,14 +1021,14 @@ int GUI_v1::controlsChangeVoice(Button *button) { return 0; } -int GUI_v1::controlsApply(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::controlsApply()"); +int GUI_LoK::controlsApply(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::controlsApply()"); _vm->writeSettings(); return cancelSubMenu(button); } -int GUI_v1::scrollUp(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::scrollUp()"); +int GUI_LoK::scrollUp(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::scrollUp()"); updateMenuButton(button); if (_savegameOffset > 0) { @@ -1034,8 +1039,8 @@ int GUI_v1::scrollUp(Button *button) { return 0; } -int GUI_v1::scrollDown(Button *button) { - debugC(9, kDebugLevelGUI, "GUI_v1::scrollDown()"); +int GUI_LoK::scrollDown(Button *button) { + debugC(9, kDebugLevelGUI, "GUI_LoK::scrollDown()"); updateMenuButton(button); _savegameOffset++; @@ -1047,7 +1052,7 @@ int GUI_v1::scrollDown(Button *button) { return 0; } -void GUI_v1::fadePalette() { +void GUI_LoK::fadePalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) return; @@ -1067,7 +1072,7 @@ void GUI_v1::fadePalette() { _screen->fadePalette(_screen->_currentPalette, 2); } -void GUI_v1::restorePalette() { +void GUI_LoK::restorePalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) return; @@ -1077,8 +1082,8 @@ void GUI_v1::restorePalette() { #pragma mark - -void KyraEngine_v1::drawAmulet() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::drawAmulet()"); +void KyraEngine_LoK::drawAmulet() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::drawAmulet()"); static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1}; static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1}; static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1}; diff --git a/engines/kyra/gui_v1.h b/engines/kyra/gui_lok.h index 5f6d438689..607ef0b605 100644 --- a/engines/kyra/gui_v1.h +++ b/engines/kyra/gui_lok.h @@ -23,77 +23,84 @@ * */ -#ifndef KYRA_GUI_V1_H -#define KYRA_GUI_V1_H +#ifndef KYRA_GUI_LOK_H +#define KYRA_GUI_LOK_H #include "kyra/gui.h" namespace Kyra { #define GUI_V1_BUTTON(button, a, b, c, d, e, f, g, h, i, j, k) \ - button.nextButton = 0; \ - button.index = a; \ - button.unk6 = button.unk8 = 0; \ - button.data0Val1 = b; \ - button.data1Val1 = c; \ - button.data2Val1 = d; \ - button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \ - button.flags = e; \ - button.dimTableIndex = f; \ - button.x = g; \ - button.y = h; \ - button.width = i; \ - button.height = j; \ - button.flags2 = k + do { \ + button.nextButton = 0; \ + button.index = a; \ + button.unk6 = button.unk8 = 0; \ + button.data0Val1 = b; \ + button.data1Val1 = c; \ + button.data2Val1 = d; \ + button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \ + button.flags = e; \ + button.dimTableIndex = f; \ + button.x = g; \ + button.y = h; \ + button.width = i; \ + button.height = j; \ + button.flags2 = k; \ + button.mouseWheel = 0; \ + } while (0) #define GUI_V1_MENU(menu, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \ - menu.x = a; \ - menu.y = b; \ - menu.width = c; \ - menu.height = d; \ - menu.bkgdColor = e; \ - menu.color1 = f; \ - menu.color2 = g; \ - menu.menuNameString = h; \ - menu.textColor = i; \ - menu.titleX = j; \ - menu.titleY = k; \ - menu.highlightedItem = l; \ - menu.numberOfItems = m; \ - menu.scrollUpButtonX = n; \ - menu.scrollUpButtonY = o; \ - menu.scrollDownButtonX = p; \ - menu.scrollDownButtonY = q + do { \ + menu.x = a; \ + menu.y = b; \ + menu.width = c; \ + menu.height = d; \ + menu.bkgdColor = e; \ + menu.color1 = f; \ + menu.color2 = g; \ + menu.menuNameString = h; \ + menu.textColor = i; \ + menu.titleX = j; \ + menu.titleY = k; \ + menu.highlightedItem = l; \ + menu.numberOfItems = m; \ + menu.scrollUpButtonX = n; \ + menu.scrollUpButtonY = o; \ + menu.scrollDownButtonX = p; \ + menu.scrollDownButtonY = q; \ + } while (0) #define GUI_V1_MENU_ITEM(item, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) \ - item.enabled = a; \ - item.itemString = d; \ - item.x = e; \ - item.y = g; \ - item.width = h; \ - item.height = i; \ - item.textColor = j; \ - item.highlightColor = k; \ - item.titleX = l; \ - item.bkgdColor = n; \ - item.color1 = o; \ - item.color2 = p; \ - item.saveSlot = q; \ - item.labelString = r; \ - item.labelX = s; \ - item.labelY = t; \ - item.unk1F = v - -class KyraEngine_v1; - -class GUI_v1 : public GUI { - friend class KyraEngine_v1; + do { \ + item.enabled = a; \ + item.itemString = d; \ + item.x = e; \ + item.y = g; \ + item.width = h; \ + item.height = i; \ + item.textColor = j; \ + item.highlightColor = k; \ + item.titleX = l; \ + item.bkgdColor = n; \ + item.color1 = o; \ + item.color2 = p; \ + item.saveSlot = q; \ + item.labelString = r; \ + item.labelX = s; \ + item.labelY = t; \ + item.unk1F = v; \ + } while (0) + +class KyraEngine_LoK; + +class GUI_LoK : public GUI { + friend class KyraEngine_LoK; public: - GUI_v1(KyraEngine_v1 *vm, Screen_v1 *screen); - ~GUI_v1(); + GUI_LoK(KyraEngine_LoK *vm, Screen_LoK *screen); + ~GUI_LoK(); void processButton(Button *button); - int processButtonList(Button *buttonList, uint16 inputFlags); + int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel); int buttonMenuCallback(Button *caller); private: @@ -147,8 +154,8 @@ private: const char *getMenuItemTitle(const MenuItem &menuItem) { return menuItem.itemString; } const char *getMenuItemLabel(const MenuItem &menuItem) { return menuItem.labelString; } - KyraEngine_v1 *_vm; - Screen_v1 *_screen; + KyraEngine_LoK *_vm; + Screen_LoK *_screen; bool _menuRestoreScreen; uint8 _toplevelMenu; diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 8d27938aff..6822b303c3 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -194,7 +194,7 @@ void KyraEngine_MR::showInventory() { _screen->hideMouse(); if (_itemInHand < 0) { - _handItemSet = -1; + _mouseState = -1; _screen->setMouseCursor(0, 0, getShapePtr(0)); } @@ -559,6 +559,7 @@ int KyraEngine_MR::buttonInventory(Button *button) { } int KyraEngine_MR::buttonMoodChange(Button *button) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::buttonMoodChange(%p)", (const void*)button); if (queryGameFlag(0x219)) { snd_playSoundEffect(0x0D, 0xC8); return 0; @@ -626,6 +627,7 @@ int KyraEngine_MR::buttonMoodChange(Button *button) { } int KyraEngine_MR::buttonShowScore(Button *button) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::buttonShowScore(%p)", (const void*)button); strcpy(_stringBuffer, (const char*)getTableEntry(_cCodeFile, 18)); char *buffer = _stringBuffer; @@ -649,6 +651,7 @@ int KyraEngine_MR::buttonShowScore(Button *button) { } int KyraEngine_MR::buttonJesterStaff(Button *button) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::buttonJesterStaff(%p)", (const void*)button); makeCharFacingMouse(); if (_itemInHand == 27) { _screen->hideMouse(); @@ -679,6 +682,457 @@ int KyraEngine_MR::buttonJesterStaff(Button *button) { return 0; } +void KyraEngine_MR::showAlbum() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::showAlbum()"); + if (!_screen->isMouseVisible() || queryGameFlag(4) || _mouseState != -1) + return; + + if (!loadLanguageFile("ALBUM.", _album.file)) + error("Couldn't load ALBUM"); + + if (!queryGameFlag(0x8B)) + _album.wsa->open("ALBMGNTH.WSA", 1, 0); + _album.backUpRect = new uint8[3100]; + assert(_album.backUpRect); + _album.backUpPage = new uint8[64000]; + assert(_album.backUpPage); + _album.nextPage = _album.curPage; + + _screen->copyRegionToBuffer(0, 0, 0, 320, 200, _screenBuffer); + _screen->copyRegionToBuffer(4, 0, 0, 320, 200, _album.backUpPage); + + memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->fadeToBlack(9); + + int itemInHand = _itemInHand; + removeHandItem(); + + _res->loadFileToBuf("ALBUM.COL", _screen->getPalette(0), 768); + loadAlbumPage(); + loadAlbumPageWSA(); + + if (_album.leftPage.wsa->opened()) { + _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]); + _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]); + _album.leftPage.wsa->setDrawPage(2); + + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000); + } + if (_album.rightPage.wsa->opened()) { + _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]); + _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]); + _album.rightPage.wsa->setDrawPage(2); + + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000); + } + + printAlbumPageText(); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + _screen->fadePalette(_screen->getPalette(0), 9); + + processAlbum(); + + _screen->fadeToBlack(9); + _album.wsa->close(); + + setHandItem(itemInHand); + updateMouse(); + + restorePage3(); + _screen->copyBlockToPage(0, 0, 0, 320, 200, _screenBuffer); + _screen->copyBlockToPage(4, 0, 0, 320, 200, _album.backUpPage); + + memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->fadePalette(_screen->getPalette(0), 9); + + delete[] _album.backUpRect; + _album.backUpRect = 0; + delete[] _album.backUpPage; + _album.backUpPage = 0; + delete[] _album.file; + _album.file = 0; + + _eventList.clear(); +} + +void KyraEngine_MR::loadAlbumPage() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::loadAlbumPage()"); + + char filename[16]; + int num = _album.curPage / 2; + + if (num == 0) { + strcpy(filename, "ALBUM0.CPS"); + } else if (num >= 1 && num <= 6) { + --num; + num %= 2; + snprintf(filename, 16, "ALBUM%d.CPS", num+1); + } else { + strcpy(filename, "ALBUM3.CPS"); + } + + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 4, Screen::CR_NO_P_CHECK); + _screen->loadBitmap(filename, 3, 3, 0); +} + +void KyraEngine_MR::loadAlbumPageWSA() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::loadAlbumPageWSA()"); + char filename[16]; + + _album.leftPage.curFrame = 0; + _album.leftPage.maxFrame = 0; + _album.leftPage.wsa->close(); + + _album.rightPage.curFrame = 0; + _album.rightPage.maxFrame = 0; + _album.rightPage.wsa->close(); + + if (_album.curPage) { + snprintf(filename, 16, "PAGE%x.WSA", _album.curPage); + _album.leftPage.wsa->open(filename, 1, 0); + _album.leftPage.maxFrame = _album.leftPage.wsa->frames()-1; + } + + if (_album.curPage != 14) { + snprintf(filename, 16, "PAGE%x.WSA", _album.curPage+1); + _album.rightPage.wsa->open(filename, 1, 0); + _album.rightPage.maxFrame = _album.leftPage.wsa->frames()-1; + } +} + +void KyraEngine_MR::printAlbumPageText() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::printAlbumPageText()"); + + static const uint8 posY[] = { + 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5A, 0x5A, + 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x3C + }; + + const int leftY = posY[_album.curPage]; + const int rightY = posY[_album.curPage+1]; + + for (int i = 0; i < 5; ++i) { + const char *str = (const char *)getTableEntry(_album.file, _album.curPage*5+i); + int y = i * 10 + leftY + 20; + printAlbumText(2, str, 20, y, 10); + } + + for (int i = 0; i < 5; ++i) { + const char *str = (const char *)getTableEntry(_album.file, (_album.curPage+1)*5+i); + int y = i * 10 + rightY + 20; + printAlbumText(2, str, 176, y, 10); + } + + albumBackUpRect(); +} + +void KyraEngine_MR::printAlbumText(int page, const char *str, int x, int y, uint8 c0) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::printAlbumText(%d, '%s', %d, %d, %d)", page, str, x, y, c0); + int oldPage = _screen->_curPage; + _screen->_curPage = page; + + static const uint8 colorMap[] = { 0, 0x87, 0xA3, 0 }; + _screen->setTextColor(colorMap, 0, 3); + + Screen::FontId oldFont = _screen->setFont(Screen::FID_BOOKFONT_FNT); + _screen->_charWidth = -2; + + _screen->printText(str, x, y, c0, 0); + + _screen->_charWidth = 0; + _screen->setFont(oldFont); + _screen->_curPage = oldPage; +} + +void KyraEngine_MR::processAlbum() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::processAlbum()"); + Button albumButtons[5]; + + GUI_V2_BUTTON(albumButtons[0], 36, 0, 0, 1, 1, 1, 0x4487, 0, 130, 190, 10, 10, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + albumButtons[0].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumPrevPage); + GUI_V2_BUTTON(albumButtons[1], 37, 0, 0, 1, 1, 1, 0x4487, 0, 177, 190, 10, 10, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + albumButtons[1].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumNextPage); + GUI_V2_BUTTON(albumButtons[2], 38, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 320, 8, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + albumButtons[2].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumClose); + GUI_V2_BUTTON(albumButtons[3], 39, 0, 0, 1, 1, 1, 0x4487, 0, 8, 8, 144, 180, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + albumButtons[3].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumPrevPage); + GUI_V2_BUTTON(albumButtons[4], 40, 0, 0, 1, 1, 1, 0x4487, 0, 170, 8, 142, 180, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + albumButtons[4].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumNextPage); + + Button *buttonList = 0; + for (int i = 0; i < 5; ++i) + buttonList = _gui->addButtonToList(buttonList, &albumButtons[i]); + + _album.leftPage.timer = _album.rightPage.timer = _system->getMillis(); + albumNewPage(); + _album.running = true; + + while (_album.running && !_quitFlag) { + updateInput(); + checkInput(buttonList); + removeInputTop(); + + musicUpdate(0); + + if (_album.curPage != _album.nextPage) { + int oldPage = _album.curPage; + _album.curPage = _album.nextPage; + + _album.leftPage.wsa->close(); + _album.rightPage.wsa->close(); + + loadAlbumPage(); + loadAlbumPageWSA(); + + if (_album.leftPage.wsa->opened()) { + _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]); + _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]); + _album.leftPage.wsa->setDrawPage(2); + + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000); + } + if (_album.rightPage.wsa->opened()) { + _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]); + _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]); + _album.rightPage.wsa->setDrawPage(2); + + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000); + } + + printAlbumPageText(); + + snd_playSoundEffect(0x85, 0x80); + albumSwitchPages(oldPage, _album.nextPage, 4); + + _album.leftPage.timer = _album.rightPage.timer = 0; + albumNewPage(); + + _eventList.clear(); + } + + albumUpdateAnims(); + _system->delayMillis(10); + } + + _album.leftPage.wsa->close(); + _album.rightPage.wsa->close(); +} + +void KyraEngine_MR::albumNewPage() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumNewPage()"); + int page = _album.nextPage / 2; + if (!queryGameFlag(0x84+page)) { + albumAnim1(); + delayWithTicks(8); + + int id = _album.curPage / 2 + 100; + albumChat((const char *)getTableEntry(_album.file, id), 205, id); + + if (id == 107) { + _screen->copyRegion(76, 100, 76, 100, 244, 100, 2, 0, Screen::CR_NO_P_CHECK); + albumChat((const char *)getTableEntry(_album.file, 108), 205, 108); + _screen->copyRegion(76, 100, 76, 100, 244, 100, 2, 0, Screen::CR_NO_P_CHECK); + albumChat((const char *)getTableEntry(_album.file, 109), 205, 109); + } + + delayWithTicks(5); + albumAnim2(); + + setGameFlag(0x84+page); + _album.isPage14 = (_album.nextPage == 14); + } +} + +void KyraEngine_MR::albumUpdateAnims() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumUpdateAnims()"); + if (_album.nextPage == 14 && !_album.isPage14) + return; + + uint32 nextRun = 0; + + nextRun = _album.leftPage.timer + 5 * _tickLength; + if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) { + _album.leftPage.wsa->setX(_albumWSAX[_album.nextPage+0]); + _album.leftPage.wsa->setY(_albumWSAY[_album.nextPage+0]); + _album.leftPage.wsa->setDrawPage(2); + + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 0x4000); + _screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK); + + ++_album.leftPage.curFrame; + _album.leftPage.timer = _system->getMillis(); + + if (_album.leftPage.curFrame > _album.leftPage.maxFrame) { + _album.leftPage.curFrame = 0; + if (_album.nextPage == 14) { + _album.isPage14 = false; + _album.leftPage.timer += 100000 * _tickLength; + } else { + _album.leftPage.timer += 180 * _tickLength; + } + } + } + + nextRun = _album.rightPage.timer + 5 * _tickLength; + if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) { + _album.rightPage.wsa->setX(_albumWSAX[_album.nextPage+1]); + _album.rightPage.wsa->setY(_albumWSAY[_album.nextPage+1]); + _album.rightPage.wsa->setDrawPage(2); + + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 0x4000); + _screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK); + + ++_album.rightPage.curFrame; + _album.rightPage.timer = _system->getMillis(); + + if (_album.rightPage.curFrame > _album.rightPage.maxFrame) { + _album.rightPage.curFrame = 0; + _album.rightPage.timer += 180 * _tickLength; + } + } + + _screen->updateScreen(); +} + +void KyraEngine_MR::albumAnim1() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumAnim1()"); + _album.wsa->setX(-100); + _album.wsa->setY(90); + _album.wsa->setDrawPage(2); + + for (int i = 6; i >= 3; --i) { + albumRestoreRect(); + _album.wsa->displayFrame(i, 0x4000); + albumUpdateRect(); + delayWithTicks(1); + } + + albumRestoreRect(); + _album.wsa->displayFrame(14, 0x4000); + albumUpdateRect(); + delayWithTicks(1); +} + +void KyraEngine_MR::albumAnim2() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumAnim2()"); + _album.wsa->setX(-100); + _album.wsa->setY(90); + _album.wsa->setDrawPage(2); + + for (int i = 3; i <= 6; ++i) { + albumRestoreRect(); + _album.wsa->displayFrame(i, 0x4000); + albumUpdateRect(); + delayWithTicks(1); + } + + albumRestoreRect(); + _screen->copyRegion(0, 100, 0, 100, 320, 100, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); +} + +void KyraEngine_MR::albumBackUpRect() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumBackUpRect()"); + _screen->copyRegionToBuffer(2, 0, 146, 62, 50, _album.backUpRect); +} + +void KyraEngine_MR::albumRestoreRect() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumRestoreRect()"); + _screen->copyBlockToPage(2, 0, 146, 62, 50, _album.backUpRect); +} + +void KyraEngine_MR::albumUpdateRect() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumUpdateRect()"); + _screen->copyRegion(0, 146, 0, 146, 62, 50, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); +} + +void KyraEngine_MR::albumSwitchPages(int oldPage, int newPage, int srcPage) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumSwitchPages(%d, %d, %d)", oldPage, newPage, srcPage); + if (newPage > oldPage) { + _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x64, 0xBA, srcPage, 0, 2); + + _screen->copyRegion(260, 7, 260, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x32, 0xBA, srcPage, 0, 2); + + _screen->copyRegion(210, 7, 210, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->copyRegion(160, 7, 160, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->wsaFrameAnimationStep(0x10, 0x07, 0x6E, 0x07, 0x96, 0xBA, 0x32, 0xBA, 2, 0, 2); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->wsaFrameAnimationStep(0x10, 0x07, 0x3C, 0x07, 0x96, 0xBA, 0x64, 0xBA, 2, 0, 2); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->copyRegion(10, 7, 10, 7, 150, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } else { + _screen->wsaFrameAnimationStep(0x0A, 0x07, 0x3C, 0x07, 0x96, 0xBA, 0x64, 0xBA, srcPage, 0, 2); + + _screen->copyRegion(10, 7, 10, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->wsaFrameAnimationStep(0x0A, 0x07, 0x6E, 0x07, 0x96, 0xBA, 0x32, 0xBA, srcPage, 0, 2); + + _screen->copyRegion(60, 7, 60, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->copyRegion(110, 7, 110, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x32, 0xBA, 2, 0, 2); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x64, 0xBA, 2, 0, 2); + _screen->updateScreen(); + delayWithTicks(1); + + _screen->copyRegion(160, 7, 160, 7, 150, 186, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } +} + +int KyraEngine_MR::albumNextPage(Button *caller) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumNextPage(%p)", (const void *)caller); + _album.nextPage = _album.curPage + 2; + if (_album.nextPage >= 16) { + _album.nextPage -= 2; + _album.running = false; + } + return 0; +} + +int KyraEngine_MR::albumPrevPage(Button *caller) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumPrevPage(%p)", (const void *)caller); + _album.nextPage = _album.curPage - 2; + if (_album.nextPage < 0) { + _album.nextPage = 0; + _album.running = false; + } + return 0; +} + +int KyraEngine_MR::albumClose(Button *caller) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumClose(%p)", (const void *)caller); + _album.running = false; + return 0; +} + #pragma mark - GUI_MR::GUI_MR(KyraEngine_MR *vm) : GUI_v2(vm), _vm(vm), _screen(vm->_screen) { @@ -704,6 +1158,11 @@ void GUI_MR::flagButtonDisable(Button *button) { } } +void GUI_MR::getInput() { + _vm->musicUpdate(0); + GUI_v2::getInput(); +} + const char *GUI_MR::getMenuTitle(const Menu &menu) { if (!menu.menuNameId) return 0; @@ -784,6 +1243,8 @@ int GUI_MR::quitGame(Button *caller) { } int GUI_MR::optionsButton(Button *button) { + PauseTimer pause(*_vm->_timer); + _vm->musicUpdate(0); _screen->hideMouse(); @@ -801,8 +1262,8 @@ int GUI_MR::optionsButton(Button *button) { _vm->showMessage(0, 0xF0, 0xF0); - if (_vm->_handItemSet < -1) { - _vm->_handItemSet = -1; + if (_vm->_mouseState < -1) { + _vm->_mouseState = -1; _screen->hideMouse(); _screen->setMouseCursor(1, 1, _vm->getShapePtr(0)); _screen->showMouse(); @@ -938,6 +1399,7 @@ int GUI_MR::loadMenu(Button *caller) { } else if (_vm->_gameToLoad >= 0) { restorePage1(_vm->_screenBuffer); restorePalette(); + _vm->_menuDirectlyToLoad = false; _vm->loadGame(_vm->getSavegameFilename(_vm->_gameToLoad)); if (_vm->_gameToLoad == 0) { _restartGame = true; @@ -982,7 +1444,7 @@ int GUI_MR::gameOptions(Button *caller) { if (textEnabled && !_vm->textEnabled() && !_vm->speechEnabled()) { _vm->_configVoice = 1; - _vm->setVolume(KyraEngine::kVolumeSpeech, 75); + _vm->setVolume(KyraEngine_v1::kVolumeSpeech, 75); choiceDialog(0x1E, 0); } @@ -1077,15 +1539,26 @@ int GUI_MR::toggleSkipSupport(Button *caller) { return 0; } +int GUI_MR::toggleHeliumMode(Button *caller) { + updateMenuButton(caller); + _vm->_configHelium ^= 1; + if (_vm->_configHelium) + _audioOptions.item[3].itemId = 18; + else + _audioOptions.item[3].itemId = 17; + renewHighlight(_audioOptions); + return 0; +} + int GUI_MR::audioOptions(Button *caller) { updateMenuButton(caller); restorePage1(_vm->_screenBuffer); backUpPage1(_vm->_screenBuffer); - //if (_configHelium) - // _audioOptions.item[3].itemId = 18; - //else + if (_vm->_configHelium) + _audioOptions.item[3].itemId = 18; + else _audioOptions.item[3].itemId = 17; initMenu(_audioOptions); @@ -1124,7 +1597,7 @@ int GUI_MR::audioOptions(Button *caller) { restorePage1(_vm->_screenBuffer); backUpPage1(_vm->_screenBuffer); - if (speechEnabled && !_vm->textEnabled() && (!_vm->speechEnabled() || _vm->getVolume(KyraEngine::kVolumeSpeech) == 2)) { + if (speechEnabled && !_vm->textEnabled() && (!_vm->speechEnabled() || _vm->getVolume(KyraEngine_v1::kVolumeSpeech) == 2)) { _vm->_configVoice = 0; choiceDialog(0x1D, 0); } @@ -1147,7 +1620,7 @@ int GUI_MR::sliderHandler(Button *caller) { assert(button >= 0 && button <= 3); - int oldVolume = _vm->getVolume(KyraEngine::kVolumeEntry(button)); + int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); int newVolume = oldVolume; if (caller->index >= 24 && caller->index <= 27) @@ -1175,7 +1648,7 @@ int GUI_MR::sliderHandler(Button *caller) { _vm->_configVoice = 1; } - _vm->setVolume(KyraEngine::kVolumeEntry(button), newVolume); + _vm->setVolume(KyraEngine_v1::kVolumeEntry(button), newVolume); switch (button) { case 0: @@ -1200,7 +1673,7 @@ int GUI_MR::sliderHandler(Button *caller) { if (playSoundEffect) _vm->snd_playSoundEffect(0x18, 0xC8); else if (lastMusicCommand >= 0) - _vm->snd_playWanderScoreViaMap(lastMusicCommand, 1); + _vm->snd_playWanderScoreViaMap(lastMusicCommand, 0); _screen->updateScreen(); return 0; @@ -1212,7 +1685,7 @@ void GUI_MR::drawSliderBar(int slider, const uint8 *shape) { int x = menuX + _sliderBarsPosition[slider*2+0] + 10; int y = menuY + _sliderBarsPosition[slider*2+1]; - int position = _vm->getVolume(KyraEngine::kVolumeEntry(slider)); + int position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider)); position = MAX(2, position); position = MIN(97, position); diff --git a/engines/kyra/gui_mr.h b/engines/kyra/gui_mr.h index d73b21b73b..5bd3569031 100644 --- a/engines/kyra/gui_mr.h +++ b/engines/kyra/gui_mr.h @@ -48,6 +48,8 @@ public: int optionsButton(Button *button); private: + void getInput(); + const char *getMenuTitle(const Menu &menu); const char *getMenuItemTitle(const MenuItem &menuItem); const char *getMenuItemLabel(const MenuItem &menuItem); @@ -77,6 +79,7 @@ private: int changeLanguage(Button *caller); int toggleStudioSFX(Button *caller); int toggleSkipSupport(Button *caller); + int toggleHeliumMode(Button *caller); KyraEngine_MR *_vm; Screen_MR *_screen; diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index d835c4f8d5..2819c4f077 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -43,6 +43,8 @@ GUI_v2::GUI_v2(KyraEngine_v2 *vm) : GUI(vm), _vm(vm), _screen(vm->screen_v2()) { _scrollUpFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::scrollUpButton); _scrollDownFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::scrollDownButton); _sliderHandlerFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::sliderHandler); + _savegameOffset = 0; + _isDeleteMenu = false; } Button *GUI_v2::addButtonToList(Button *list, Button *newButton) { @@ -138,7 +140,7 @@ void GUI_v2::processButton(Button *button) { _screen->updateScreen(); } -int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag) { +int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseWheel) { static uint16 flagsModifier = 0; if (!buttonList) @@ -234,6 +236,12 @@ int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag) { } bool unk1 = false; + + if (mouseWheel && buttonList->mouseWheel == mouseWheel) { + progress = true; + unk1 = true; + } + if (!progress) buttonList->flags2 &= ~6; @@ -407,6 +415,8 @@ void GUI_v2::getInput() { _isOptionsMenu = false; _isDeleteMenu = false; } + + _vm->delay(10); } void GUI_v2::renewHighlight(Menu &menu) { @@ -441,7 +451,7 @@ void GUI_v2::setupSavegameNames(Menu &menu, int num) { if (_isSaveMenu && _savegameOffset == 0) startSlot = 1; - KyraEngine::SaveHeader header; + KyraEngine_v1::SaveHeader header; Common::InSaveFile *in; for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != 0) { @@ -844,7 +854,7 @@ void GUI_v2::checkTextfieldInput() { } } - processButtonList(_menuButtonList, keys | 0x8000); + processButtonList(_menuButtonList, keys | 0x8000, 0); } void GUI_v2::drawTextfieldBlock(int x, int y, uint8 c) { diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h index 4e94b58742..161752627b 100644 --- a/engines/kyra/gui_v2.h +++ b/engines/kyra/gui_v2.h @@ -31,65 +31,72 @@ namespace Kyra { #define GUI_V2_BUTTON(button, a, b, c, d, e, f, h, i, j, k, l, m, n, o, p, q, r, s, t) \ - button.nextButton = 0; \ - button.index = a; \ - button.unk6 = b; \ - button.unk8 = c; \ - button.data0Val1 = d; \ - button.data1Val1 = e; \ - button.data2Val1 = f; \ - button.flags = h; \ - button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \ - button.dimTableIndex = i; \ - button.x = j; \ - button.y = k; \ - button.width = l; \ - button.height = m; \ - button.data0Val2 = n; \ - button.data0Val3 = o; \ - button.data1Val2 = p; \ - button.data1Val3 = q; \ - button.data2Val2 = r; \ - button.data2Val3 = s; \ - button.flags2 = t; + do { \ + button.nextButton = 0; \ + button.index = a; \ + button.unk6 = b; \ + button.unk8 = c; \ + button.data0Val1 = d; \ + button.data1Val1 = e; \ + button.data2Val1 = f; \ + button.flags = h; \ + button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \ + button.dimTableIndex = i; \ + button.x = j; \ + button.y = k; \ + button.width = l; \ + button.height = m; \ + button.data0Val2 = n; \ + button.data0Val3 = o; \ + button.data1Val2 = p; \ + button.data1Val3 = q; \ + button.data2Val2 = r; \ + button.data2Val3 = s; \ + button.flags2 = t; \ + button.mouseWheel = 0; \ + } while (0) #define GUI_V2_MENU(menu, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \ - menu.x = a; \ - menu.y = b; \ - menu.width = c; \ - menu.height = d; \ - menu.bkgdColor = e; \ - menu.color1 = f; \ - menu.color2 = g; \ - menu.menuNameId = h; \ - menu.textColor = i; \ - menu.titleX = j; \ - menu.titleY = k; \ - menu.highlightedItem = l; \ - menu.numberOfItems = m; \ - menu.scrollUpButtonX = n; \ - menu.scrollUpButtonY = o; \ - menu.scrollDownButtonX = p; \ - menu.scrollDownButtonY = q + do { \ + menu.x = a; \ + menu.y = b; \ + menu.width = c; \ + menu.height = d; \ + menu.bkgdColor = e; \ + menu.color1 = f; \ + menu.color2 = g; \ + menu.menuNameId = h; \ + menu.textColor = i; \ + menu.titleX = j; \ + menu.titleY = k; \ + menu.highlightedItem = l; \ + menu.numberOfItems = m; \ + menu.scrollUpButtonX = n; \ + menu.scrollUpButtonY = o; \ + menu.scrollDownButtonX = p; \ + menu.scrollDownButtonY = q; \ + } while (0) #define GUI_V2_MENU_ITEM(item, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \ - item.enabled = a; \ - item.itemId = b; \ - item.x = c; \ - item.y = d; \ - item.width = e; \ - item.height = f; \ - item.textColor = g; \ - item.highlightColor = h; \ - item.titleX = i; \ - item.bkgdColor = j; \ - item.color1 = k; \ - item.color2 = l; \ - item.saveSlot = m; \ - item.labelId = n; \ - item.labelX = o; \ - item.labelY = p; \ - item.unk1F = q + do { \ + item.enabled = a; \ + item.itemId = b; \ + item.x = c; \ + item.y = d; \ + item.width = e; \ + item.height = f; \ + item.textColor = g; \ + item.highlightColor = h; \ + item.titleX = i; \ + item.bkgdColor = j; \ + item.color1 = k; \ + item.color2 = l; \ + item.saveSlot = m; \ + item.labelId = n; \ + item.labelX = o; \ + item.labelY = p; \ + item.unk1F = q; \ + } while (0) class KyraEngine_v2; class Screen_v2; @@ -103,7 +110,7 @@ public: Button *addButtonToList(Button *list, Button *newButton); void processButton(Button *button); - int processButtonList(Button *button, uint16 inputFlag); + int processButtonList(Button *button, uint16 inputFlag, int8 mouseWheel); protected: void updateButton(Button *button); @@ -125,7 +132,7 @@ protected: virtual uint8 textFieldColor2() const = 0; virtual uint8 textFieldColor3() const = 0; protected: - void getInput(); + virtual void getInput(); Button _menuButtons[7]; Button _scrollUpButton; diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp index da3062fe2c..4dfc73a5ad 100644 --- a/engines/kyra/items_hof.cpp +++ b/engines/kyra/items_hof.cpp @@ -83,7 +83,7 @@ void KyraEngine_HoF::updateWaterFlasks() { bool KyraEngine_HoF::dropItem(int unk1, uint16 item, int x, int y, int unk2) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::dropItem(%d, %u, %d, %d, %d)", unk1, item, x, y, unk2); - if (_handItemSet <= -1) + if (_mouseState <= -1) return false; bool success = processItemDrop(_mainCharacter.sceneId, item, x, y, unk1, unk2); diff --git a/engines/kyra/items_v1.cpp b/engines/kyra/items_lok.cpp index ae3ba2821a..8eb62c20c2 100644 --- a/engines/kyra/items_v1.cpp +++ b/engines/kyra/items_lok.cpp @@ -23,14 +23,14 @@ * */ -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/seqplayer.h" #include "kyra/screen.h" #include "kyra/resource.h" #include "kyra/sound.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" #include "kyra/text.h" #include "common/system.h" @@ -38,7 +38,7 @@ namespace Kyra { -int KyraEngine_v1::findDuplicateItemShape(int shape) { +int KyraEngine_LoK::findDuplicateItemShape(int shape) { static uint8 dupTable[] = { 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47, 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a, @@ -55,8 +55,8 @@ int KyraEngine_v1::findDuplicateItemShape(int shape) { return -1; } -void KyraEngine_v1::addToNoDropRects(int x, int y, int w, int h) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h); +void KyraEngine_LoK::addToNoDropRects(int x, int y, int w, int h) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h); for (int rect = 0; rect < 11; ++rect) { if (_noDropRects[rect].x == -1) { _noDropRects[rect].x = x; @@ -68,13 +68,13 @@ void KyraEngine_v1::addToNoDropRects(int x, int y, int w, int h) { } } -void KyraEngine_v1::clearNoDropRects() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::clearNoDropRects()"); +void KyraEngine_LoK::clearNoDropRects() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::clearNoDropRects()"); memset(_noDropRects, -1, sizeof(_noDropRects)); } -byte KyraEngine_v1::findFreeItemInScene(int scene) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::findFreeItemInScene(%d)", scene); +byte KyraEngine_LoK::findFreeItemInScene(int scene) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::findFreeItemInScene(%d)", scene); assert(scene < _roomTableSize); Room *room = &_roomTable[scene]; for (int i = 0; i < 12; ++i) { @@ -84,8 +84,8 @@ byte KyraEngine_v1::findFreeItemInScene(int scene) { return 0xFF; } -byte KyraEngine_v1::findItemAtPos(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::findItemAtPos(%d, %d)", x, y); +byte KyraEngine_LoK::findItemAtPos(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::findItemAtPos(%d, %d)", x, y); assert(_currentCharacter->sceneId < _roomTableSize); const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable; const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos; @@ -120,8 +120,8 @@ byte KyraEngine_v1::findItemAtPos(int x, int y) { return returnValue; } -void KyraEngine_v1::placeItemInGenericMapScene(int item, int index) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::placeItemInGenericMapScene(%d, %d)", item, index); +void KyraEngine_LoK::placeItemInGenericMapScene(int item, int index) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::placeItemInGenericMapScene(%d, %d)", item, index); static const uint16 itemMapSceneMinTable[] = { 0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000 }; @@ -175,32 +175,32 @@ void KyraEngine_v1::placeItemInGenericMapScene(int item, int index) { } } -void KyraEngine_v1::createMouseItem(int item) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::createMouseItem(%d)", item); +void KyraEngine_LoK::setHandItem(uint16 item) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setHandItem(%u)", item); _screen->hideMouse(); setMouseItem(item); _itemInHand = item; _screen->showMouse(); } -void KyraEngine_v1::destroyMouseItem() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::destroyMouseItem()"); +void KyraEngine_LoK::removeHandItem() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::removeHandItem()"); _screen->hideMouse(); _screen->setMouseCursor(1, 1, _shapes[0]); _itemInHand = -1; _screen->showMouse(); } -void KyraEngine_v1::setMouseItem(int item) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setMouseItem(%d)", item); - if (item == -1) +void KyraEngine_LoK::setMouseItem(uint16 item) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setMouseItem(%u)", item); + if (item == 0xFFFF) _screen->setMouseCursor(1, 1, _shapes[6]); else _screen->setMouseCursor(8, 15, _shapes[216+item]); } -void KyraEngine_v1::wipeDownMouseItem(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::wipeDownMouseItem(%d, %d)", xpos, ypos); +void KyraEngine_LoK::wipeDownMouseItem(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::wipeDownMouseItem(%d, %d)", xpos, ypos); if (_itemInHand == -1) return; xpos -= 8; @@ -222,12 +222,12 @@ void KyraEngine_v1::wipeDownMouseItem(int xpos, int ypos) { } restoreItemRect1(xpos, ypos); _screen->resetShapeHeight(_shapes[216+_itemInHand]); - destroyMouseItem(); + removeHandItem(); _screen->showMouse(); } -void KyraEngine_v1::setupSceneItems() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setupSceneItems()"); +void KyraEngine_LoK::setupSceneItems() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setupSceneItems()"); uint16 sceneId = _currentCharacter->sceneId; assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; @@ -264,8 +264,8 @@ void KyraEngine_v1::setupSceneItems() { } } -int KyraEngine_v1::countItemsInScene(uint16 sceneId) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::countItemsInScene(%d)", sceneId); +int KyraEngine_LoK::countItemsInScene(uint16 sceneId) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::countItemsInScene(%d)", sceneId); assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; @@ -279,8 +279,8 @@ int KyraEngine_v1::countItemsInScene(uint16 sceneId) { return items; } -int KyraEngine_v1::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2); +int KyraEngine_LoK::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2); int freeItem = -1; uint8 itemIndex = findItemAtPos(x, y); if (unk1) @@ -420,7 +420,7 @@ int KyraEngine_v1::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int itemSpecialFX(x, y, item); if (unk1 == 0) - destroyMouseItem(); + removeHandItem(); itemDropDown(x, y, destX, destY, freeItem, item); @@ -432,8 +432,8 @@ int KyraEngine_v1::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int return 1; } -void KyraEngine_v1::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex); +void KyraEngine_LoK::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex); _screen->hideMouse(); _animator->animRemoveGameItem(itemIndex); assert(sceneId < _roomTableSize); @@ -452,8 +452,8 @@ void KyraEngine_v1::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { clickEventHandler2(); } -void KyraEngine_v1::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y); +void KyraEngine_LoK::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y); assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; currentRoom->itemsTable[itemIndex] = item; @@ -462,8 +462,8 @@ void KyraEngine_v1::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int currentRoom->needInit[itemIndex] = 1; } -int KyraEngine_v1::checkNoDropRects(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::checkNoDropRects(%d, %d)", x, y); +int KyraEngine_LoK::checkNoDropRects(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::checkNoDropRects(%d, %d)", x, y); if (_lastProcessedItemHeight < 1 || _lastProcessedItemHeight > 16) _lastProcessedItemHeight = 16; if (_noDropRects[0].x == -1) @@ -492,8 +492,8 @@ int KyraEngine_v1::checkNoDropRects(int x, int y) { return 0; } -int KyraEngine_v1::isDropable(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::isDropable(%d, %d)", x, y); +int KyraEngine_LoK::isDropable(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::isDropable(%d, %d)", x, y); x -= 8; y -= 1; @@ -507,8 +507,8 @@ int KyraEngine_v1::isDropable(int x, int y) { return 1; } -void KyraEngine_v1::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item); +void KyraEngine_LoK::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item); assert(_currentCharacter->sceneId < _roomTableSize); Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; if (x == destX && y == destY) { @@ -591,8 +591,8 @@ void KyraEngine_v1::itemDropDown(int x, int y, int destX, int destY, byte freeIt _screen->showMouse(); } -void KyraEngine_v1::dropItem(int unk1, int item, int x, int y, int unk2) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2); +void KyraEngine_LoK::dropItem(int unk1, int item, int x, int y, int unk2) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2); if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2)) return; snd_playSoundEffect(54); @@ -603,16 +603,16 @@ void KyraEngine_v1::dropItem(int unk1, int item, int x, int y, int unk2) { drawSentenceCommand(_noDropList[1], 6); } -void KyraEngine_v1::itemSpecialFX(int x, int y, int item) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX(%d, %d, %d)", x, y, item); +void KyraEngine_LoK::itemSpecialFX(int x, int y, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::itemSpecialFX(%d, %d, %d)", x, y, item); if (item == 41) itemSpecialFX1(x, y, item); else itemSpecialFX2(x, y, item); } -void KyraEngine_v1::itemSpecialFX1(int x, int y, int item) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX1(%d, %d, %d)", x, y, item); +void KyraEngine_LoK::itemSpecialFX1(int x, int y, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::itemSpecialFX1(%d, %d, %d)", x, y, item); uint8 *shape = _shapes[216+item]; x -= 8; int startY = y; @@ -632,8 +632,8 @@ void KyraEngine_v1::itemSpecialFX1(int x, int y, int item) { _screen->showMouse(); } -void KyraEngine_v1::itemSpecialFX2(int x, int y, int item) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX2(%d, %d, %d)", x, y, item); +void KyraEngine_LoK::itemSpecialFX2(int x, int y, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::itemSpecialFX2(%d, %d, %d)", x, y, item); x -= 8; y -= 15; int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF); @@ -660,8 +660,8 @@ void KyraEngine_v1::itemSpecialFX2(int x, int y, int item) { restoreItemRect0(x, y); } -void KyraEngine_v1::magicOutMouseItem(int animIndex, int itemPos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::magicOutMouseItem(%d, %d)", animIndex, itemPos); +void KyraEngine_LoK::magicOutMouseItem(int animIndex, int itemPos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::magicOutMouseItem(%d, %d)", animIndex, itemPos); int videoPageBackUp = _screen->_curPage; _screen->_curPage = 0; int x = 0, y = 0; @@ -744,8 +744,8 @@ void KyraEngine_v1::magicOutMouseItem(int animIndex, int itemPos) { _screen->_curPage = videoPageBackUp; } -void KyraEngine_v1::magicInMouseItem(int animIndex, int item, int itemPos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos); +void KyraEngine_LoK::magicInMouseItem(int animIndex, int item, int itemPos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos); int videoPageBackUp = _screen->_curPage; _screen->_curPage = 0; int x = 0, y = 0; @@ -817,8 +817,8 @@ void KyraEngine_v1::magicInMouseItem(int animIndex, int item, int itemPos) { _screen->_curPage = videoPageBackUp; } -void KyraEngine_v1::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops); +void KyraEngine_LoK::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops); static const uint8 table1[] = { 0x23, 0x45, 0x55, 0x72, 0x84, 0xCF, 0x00, 0x00 }; @@ -840,8 +840,8 @@ void KyraEngine_v1::specialMouseItemFX(int shape, int x, int y, int animIndex, i processSpecialMouseItemFX(shape, x, y, tableValue, loopStart, maxLoops); } -void KyraEngine_v1::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops); +void KyraEngine_LoK::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops); uint8 shapeColorTable[16]; uint8 *shapePtr = _shapes[shape] + 10; if (_flags.useAltShapeHeader) @@ -859,8 +859,8 @@ void KyraEngine_v1::processSpecialMouseItemFX(int shape, int x, int y, int table _screen->drawShape(0, _shapes[shape], x, y, 0, 0x8000, shapeColorTable); } -void KyraEngine_v1::updatePlayerItemsForScene() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::updatePlayerItemsForScene()"); +void KyraEngine_LoK::updatePlayerItemsForScene() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::updatePlayerItemsForScene()"); if (_itemInHand >= 29 && _itemInHand < 33) { ++_itemInHand; if (_itemInHand > 33) @@ -900,7 +900,7 @@ void KyraEngine_v1::updatePlayerItemsForScene() { _screen->showMouse(); } -void KyraEngine_v1::redrawInventory(int page) { +void KyraEngine_LoK::redrawInventory(int page) { int videoPageBackUp = _screen->_curPage; _screen->_curPage = page; _screen->hideMouse(); @@ -916,26 +916,26 @@ void KyraEngine_v1::redrawInventory(int page) { _screen->updateScreen(); } -void KyraEngine_v1::backUpItemRect0(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::backUpItemRect0(%d, %d)", xpos, ypos); +void KyraEngine_LoK::backUpItemRect0(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::backUpItemRect0(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 3<<3, 24); _screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 3<<3, 24, _itemBkgBackUp[0]); } -void KyraEngine_v1::restoreItemRect0(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::restoreItemRect0(%d, %d)", xpos, ypos); +void KyraEngine_LoK::restoreItemRect0(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::restoreItemRect0(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 3<<3, 24); _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 3<<3, 24, _itemBkgBackUp[0]); } -void KyraEngine_v1::backUpItemRect1(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::backUpItemRect1(%d, %d)", xpos, ypos); +void KyraEngine_LoK::backUpItemRect1(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::backUpItemRect1(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 4<<3, 32); _screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]); } -void KyraEngine_v1::restoreItemRect1(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::restoreItemRect1(%d, %d)", xpos, ypos); +void KyraEngine_LoK::restoreItemRect1(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::restoreItemRect1(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 4<<3, 32); _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]); } diff --git a/engines/kyra/items_mr.cpp b/engines/kyra/items_mr.cpp index 8ace9f8a3c..299c826e80 100644 --- a/engines/kyra/items_mr.cpp +++ b/engines/kyra/items_mr.cpp @@ -97,7 +97,7 @@ void KyraEngine_MR::setMouseCursor(uint16 item) { void KyraEngine_MR::setItemMouseCursor() { debugC(9, kDebugLevelMain, "KyraEngine_MR::setItemMouseCursor()"); - _handItemSet = _itemInHand; + _mouseState = _itemInHand; if (_itemInHand == -1) _screen->setMouseCursor(0, 0, _gameShapes[0]); else @@ -107,7 +107,7 @@ void KyraEngine_MR::setItemMouseCursor() { bool KyraEngine_MR::dropItem(int unk1, uint16 item, int x, int y, int unk2) { debugC(9, kDebugLevelMain, "KyraEngine_MR::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2); - if (_handItemSet <= -1) + if (_mouseState <= -1) return false; if (processItemDrop(_mainCharacter.sceneId, item, x, y, unk1, unk2)) diff --git a/engines/kyra/items_v2.cpp b/engines/kyra/items_v2.cpp index 78768c70ab..83f637b06f 100644 --- a/engines/kyra/items_v2.cpp +++ b/engines/kyra/items_v2.cpp @@ -30,7 +30,7 @@ namespace Kyra { void KyraEngine_v2::initItemList(int size) { debugC(9, kDebugLevelMain, "KyraEngine_v2::initItemList(%d)", size); - delete [] _itemList; + delete[] _itemList; _itemList = new Item[size]; assert(_itemList); @@ -112,7 +112,7 @@ void KyraEngine_v2::removeHandItem() { scr->hideMouse(); scr->setMouseCursor(0, 0, getShapePtr(0)); _itemInHand = -1; - _handItemSet = -1; + _mouseState = -1; scr->showMouse(); } diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp deleted file mode 100644 index 05d8b79a4e..0000000000 --- a/engines/kyra/kyra.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* 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 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/config-manager.h" - -#include "sound/mididrv.h" -#include "sound/mixer.h" - -#include "kyra/kyra.h" -#include "kyra/sound.h" -#include "kyra/resource.h" -#include "kyra/screen.h" -#include "kyra/text.h" -#include "kyra/timer.h" -#include "kyra/script.h" - -namespace Kyra { - -KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags) - : Engine(system), _flags(flags) { - _res = 0; - _sound = 0; - _text = 0; - _staticres = 0; - _timer = 0; - _emc = 0; - - _gameSpeed = 60; - _tickLength = (uint8)(1000.0 / _gameSpeed); - - _quitFlag = false; - - _speechFile = ""; - _trackMap = 0; - _trackMapSize = 0; - _lastMusicCommand = -1; - _curSfxFile = _curMusicTheme = -1; - - _gameToLoad = -1; - - memset(_flagsTable, 0, sizeof(_flagsTable)); - - // sets up all engine specific debug levels - Common::addSpecialDebugLevel(kDebugLevelScriptFuncs, "ScriptFuncs", "Script function debug level"); - Common::addSpecialDebugLevel(kDebugLevelScript, "Script", "Script interpreter debug level"); - Common::addSpecialDebugLevel(kDebugLevelSprites, "Sprites", "Sprite debug level"); - Common::addSpecialDebugLevel(kDebugLevelScreen, "Screen", "Screen debug level"); - Common::addSpecialDebugLevel(kDebugLevelSound, "Sound", "Sound debug level"); - Common::addSpecialDebugLevel(kDebugLevelAnimator, "Animator", "Animator debug level"); - Common::addSpecialDebugLevel(kDebugLevelMain, "Main", "Generic debug level"); - Common::addSpecialDebugLevel(kDebugLevelGUI, "GUI", "GUI debug level"); - Common::addSpecialDebugLevel(kDebugLevelSequence, "Sequence", "Sequence debug level"); - Common::addSpecialDebugLevel(kDebugLevelMovie, "Movie", "Movie debug level"); - Common::addSpecialDebugLevel(kDebugLevelTimer, "Timer", "Timer debug level"); - - system->getEventManager()->registerRandomSource(_rnd, "kyra"); -} - -int KyraEngine::init() { - registerDefaultSettings(); - - // Setup mixer - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - - if (!_flags.useDigSound) { - // We prefer AdLib over native MIDI, since our AdLib playback code is much - // more mature than our MIDI player. For example we are missing MT-32 support - // and it seems our MIDI playback code has threading issues (see bug #1506583 - // "KYRA1: Crash on exceeded polyphony" for more information). - int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/); - - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { - // TODO: currently we don't support the PC98 sound data, - // but since it has the FM-Towns data files, we just use the - // FM-Towns driver - if (_flags.gameID == GI_KYRA1) - _sound = new SoundTowns(this, _mixer); - else - _sound = new SoundTowns_v2(this, _mixer); - } else if (midiDriver == MD_ADLIB) { - _sound = new SoundAdlibPC(this, _mixer); - assert(_sound); - } else { - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - - MidiDriver *driver = MidiDriver::createMidi(midiDriver); - assert(driver); - if (native_mt32) - driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - - SoundMidiPC *soundMidiPc = new SoundMidiPC(this, _mixer, driver); - _sound = soundMidiPc; - assert(_sound); - soundMidiPc->hasNativeMT32(native_mt32); - - // Unlike some SCUMM games, it's not that the MIDI sounds are - // missing. It's just that at least at the time of writing they - // are decidedly inferior to the Adlib ones. - if (ConfMan.getBool("multi_midi")) { - SoundAdlibPC *adlib = new SoundAdlibPC(this, _mixer); - assert(adlib); - - _sound = new MixedSoundDriver(this, _mixer, soundMidiPc, adlib); - assert(_sound); - } - } - } - - if (_sound) - _sound->updateVolumeSettings(); - - _res = new Resource(this); - assert(_res); - _res->reset(); - _staticres = new StaticResource(this); - assert(_staticres); - if (!_staticres->init()) - error("_staticres->init() failed"); - if (!screen()->init()) - error("screen()->init() failed"); - _timer = new TimerManager(this, _system); - assert(_timer); - setupTimers(); - _emc = new EMCInterpreter(this); - assert(_emc); - - setupOpcodeTable(); - readSettings(); - - if (ConfMan.hasKey("save_slot")) { - _gameToLoad = ConfMan.getInt("save_slot"); - if (!saveFileLoadable(_gameToLoad)) - _gameToLoad = -1; - } - - _lang = 0; - Common::Language lang = Common::parseLanguage(ConfMan.get("language")); - - if (_flags.gameID == GI_KYRA2 || _flags.gameID == GI_KYRA3) { - switch (lang) { - case Common::EN_ANY: - case Common::EN_USA: - case Common::EN_GRB: - _lang = 0; - break; - - case Common::FR_FRA: - _lang = 1; - break; - - case Common::DE_DEU: - _lang = 2; - break; - - case Common::JA_JPN: - _lang = 3; - break; - - default: - warning("unsupported language, switching back to English"); - _lang = 0; - break; - } - } - - return 0; -} - -KyraEngine::~KyraEngine() { - for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i) - delete *i; - _opcodes.clear(); - - delete _res; - delete _staticres; - delete _sound; - delete _text; - delete _timer; - delete _emc; -} - -void KyraEngine::quitGame() { - debugC(9, kDebugLevelMain, "KyraEngine::quitGame()"); - _quitFlag = true; - // Nothing to do here -} - -Common::Point KyraEngine::getMousePos() const { - Common::Point mouse = _eventMan->getMousePos(); - - if (_flags.useHiResOverlay) { - mouse.x >>= 1; - mouse.y >>= 1; - } - - return mouse; -} - -void KyraEngine::setMousePos(int x, int y) { - if (_flags.useHiResOverlay) { - x <<= 1; - y <<= 1; - } - _system->warpMouse(x, y); -} - -int KyraEngine::setGameFlag(int flag) { - _flagsTable[flag >> 3] |= (1 << (flag & 7)); - return 1; -} - -int KyraEngine::queryGameFlag(int flag) const { - return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1); -} - -int KyraEngine::resetGameFlag(int flag) { - _flagsTable[flag >> 3] &= ~(1 << (flag & 7)); - return 0; -} - -void KyraEngine::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quitFlag) { - if (timestamp - _system->getMillis() >= 10) - delay(10, update, isMainLoop); - } -} - -void KyraEngine::delay(uint32 amount, bool update, bool isMainLoop) { - _system->delayMillis(amount); -} - -void KyraEngine::delayWithTicks(int ticks) { - delay(ticks * _tickLength); -} - -void KyraEngine::registerDefaultSettings() { - if (_flags.gameID != GI_KYRA3) - ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)); -} - -void KyraEngine::readSettings() { - _configWalkspeed = ConfMan.getInt("walkspeed"); - _configMusic = 0; - - if (!ConfMan.getBool("music_mute")) { - _configMusic = 1; - if (_flags.gameID != GI_KYRA3 && ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) - _configMusic = 2; - } - _configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1; - - if (_sound) { - _sound->enableMusic(_configMusic); - _sound->enableSFX(_configSounds); - } - - bool speechMute = ConfMan.getBool("speech_mute"); - bool subtitles = ConfMan.getBool("subtitles"); - - if (!speechMute && subtitles) - _configVoice = 2; // Voice & Text - else if (!speechMute && !subtitles) - _configVoice = 1; // Voice only - else - _configVoice = 0; // Text only - - setWalkspeed(_configWalkspeed); -} - -void KyraEngine::writeSettings() { - bool speechMute, subtitles; - - ConfMan.setInt("walkspeed", _configWalkspeed); - ConfMan.setBool("music_mute", _configMusic == 0); - if (_flags.gameID != GI_KYRA3) - ConfMan.setBool("cdaudio", _configMusic == 2); - ConfMan.setBool("sfx_mute", _configSounds == 0); - - switch (_configVoice) { - case 0: // Text only - speechMute = true; - subtitles = true; - break; - case 1: // Voice only - speechMute = false; - subtitles = false; - break; - default: // Voice & Text - speechMute = false; - subtitles = true; - break; - } - - if (_sound) { - if (!_configMusic) - _sound->beginFadeOut(); - _sound->enableMusic(_configMusic); - _sound->enableSFX(_configSounds); - } - - ConfMan.setBool("speech_mute", speechMute); - ConfMan.setBool("subtitles", subtitles); - - ConfMan.flushToDisk(); -} - -bool KyraEngine::speechEnabled() { - return _flags.isTalkie && (_configVoice == 1 || _configVoice == 2); -} - -bool KyraEngine::textEnabled() { - return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2); -} - -inline int convertValueToMixer(int value) { - value -= 2; - return (value * Audio::Mixer::kMaxMixerVolume) / 95; -} - -inline int convertValueFromMixer(int value) { - return (value * 95) / Audio::Mixer::kMaxMixerVolume + 2; -} - -void KyraEngine::setVolume(kVolumeEntry vol, uint8 value) { - switch (vol) { - case kVolumeMusic: - ConfMan.setInt("music_volume", convertValueToMixer(value)); - break; - - case kVolumeSfx: - ConfMan.setInt("sfx_volume", convertValueToMixer(value)); - break; - - case kVolumeSpeech: - ConfMan.setInt("speech_volume", convertValueToMixer(value)); - break; - } - - // Resetup mixer - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - if (_sound) - _sound->updateVolumeSettings(); -} - -uint8 KyraEngine::getVolume(kVolumeEntry vol) { - switch (vol) { - case kVolumeMusic: - return convertValueFromMixer(ConfMan.getInt("music_volume")); - break; - - case kVolumeSfx: - return convertValueFromMixer(ConfMan.getInt("sfx_volume")); - break; - - case kVolumeSpeech: - if (speechEnabled()) - return convertValueFromMixer(ConfMan.getInt("speech_volume")); - else - return 2; - break; - } - - return 2; -} - -} // End of namespace Kyra - diff --git a/engines/kyra/kyra.h b/engines/kyra/kyra.h deleted file mode 100644 index 18a4a52fe2..0000000000 --- a/engines/kyra/kyra.h +++ /dev/null @@ -1,268 +0,0 @@ -/* 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 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$ - * - */ - -#ifndef KYRA_KYRA_H -#define KYRA_KYRA_H - -#include "engines/engine.h" - -#include "common/array.h" -#include "common/events.h" - -#include "kyra/script.h" - -namespace Common { -class InSaveFile; -class OutSaveFile; -} // end of namespace Common - -class KyraMetaEngine; - -namespace Kyra { - -struct GameFlags { - Common::Language lang; - Common::Platform platform; - - bool isDemo : 1; - bool useAltShapeHeader : 1; // alternative shape header (uses 2 bytes more, those are unused though) - bool isTalkie : 1; - bool useHiResOverlay : 1; - bool useDigSound : 1; - - byte gameID; -}; - -enum { - GI_KYRA1 = 0, - GI_KYRA2 = 1, - GI_KYRA3 = 2 -}; - -struct AudioDataStruct { - const char * const *_fileList; - const int _fileListLen; - const void * const _cdaTracks; - const int _cdaNumTracks; -}; - -// TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable -// in the future we maybe merge some flags and/or create new ones -enum kDebugLevels { - kDebugLevelScriptFuncs = 1 << 0, // prints debug output of o#_* functions - kDebugLevelScript = 1 << 1, // prints debug output of "EMCInterpreter" functions - kDebugLevelSprites = 1 << 2, // prints debug output of "Sprites" functions - kDebugLevelScreen = 1 << 3, // prints debug output of "Screen" functions - kDebugLevelSound = 1 << 4, // prints debug output of "Sound" functions - kDebugLevelAnimator = 1 << 5, // prints debug output of "ScreenAnimator" functions - kDebugLevelMain = 1 << 6, // prints debug output of common "KyraEngine(_v#)" functions && "TextDisplayer" functions - kDebugLevelGUI = 1 << 7, // prints debug output of "KyraEngine*" gui functions - kDebugLevelSequence = 1 << 8, // prints debug output of "SeqPlayer" functions - kDebugLevelMovie = 1 << 9, // prints debug output of movie specific funtions - kDebugLevelTimer = 1 << 10 // prints debug output of "TimerManager" functions -}; - -enum kMusicDataID { - kMusicIntro = 0, - kMusicIngame, - kMusicFinale -}; - -class Screen; -class Resource; -class Sound; -class Movie; -class TextDisplayer; -class StaticResource; -class TimerManager; - -class KyraEngine : public Engine { -friend class Debugger; -friend class ::KyraMetaEngine; -friend class GUI; -public: - KyraEngine(OSystem *system, const GameFlags &flags); - virtual ~KyraEngine(); - - bool quit() const { return _quitFlag; } - - uint8 game() const { return _flags.gameID; } - const GameFlags &gameFlags() const { return _flags; } - - // access to Kyra specific functionallity - Resource *resource() { return _res; } - virtual Screen *screen() = 0; - virtual TextDisplayer *text() { return _text; } - Sound *sound() { return _sound; } - StaticResource *staticres() { return _staticres; } - TimerManager *timer() { return _timer; } - - uint32 tickLength() const { return _tickLength; } - - Common::RandomSource _rnd; - - // input - void setMousePos(int x, int y); - Common::Point getMousePos() const; - - // config specific - bool speechEnabled(); - bool textEnabled(); - - enum kVolumeEntry { - kVolumeMusic = 0, - kVolumeSfx = 1, - kVolumeSpeech = 2 - }; - - // volume reaches from 2 to 97 - void setVolume(kVolumeEntry vol, uint8 value); - uint8 getVolume(kVolumeEntry vol); - - // quit handling - virtual void quitGame(); - - // game flag handling - int setGameFlag(int flag); - int queryGameFlag(int flag) const; - int resetGameFlag(int flag); - - // sound - virtual void snd_playTheme(int file, int track); - virtual void snd_playSoundEffect(int id, int volume=0xFF); - virtual void snd_playWanderScoreViaMap(int command, int restart); - virtual void snd_playVoiceFile(int id) = 0; - virtual bool snd_voiceIsPlaying(); - virtual void snd_stopVoice(); - - // delay functionallity - virtual void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); - virtual void delay(uint32 millis, bool update = false, bool isMainLoop = false); - virtual void delayWithTicks(int ticks); - -protected: - virtual int go() = 0; - virtual int init(); - - // quit Handling - bool _quitFlag; - - // intern - Resource *_res; - Sound *_sound; - TextDisplayer *_text; - StaticResource *_staticres; - TimerManager *_timer; - EMCInterpreter *_emc; - - // config specific - virtual void registerDefaultSettings(); - virtual void readSettings(); - virtual void writeSettings(); - - uint8 _configWalkspeed; - - int _configMusic; - bool _configSounds; - uint8 _configVoice; - - // game speed - virtual bool skipFlag() const = 0; - virtual void resetSkipFlag(bool removeEvent = true) = 0; - - uint16 _tickLength; - uint16 _gameSpeed; - - // timer - virtual void setupTimers() = 0; - - virtual void setWalkspeed(uint8 speed) = 0; - - // detection - GameFlags _flags; - int _lang; - - // opcode - virtual void setupOpcodeTable() = 0; - Common::Array<const Opcode*> _opcodes; - - // game flags - uint8 _flagsTable[100]; // TODO: check this value - - // sound - Common::String _speechFile; - - int _curMusicTheme; - int _curSfxFile; - int16 _lastMusicCommand; - - const int8 *_trackMap; - int _trackMapSize; - - // pathfinder - virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); - int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end); - int getFacingFromPointToPoint(int x, int y, int toX, int toY); - int getOppositeFacingDirection(int dir); - void changePosTowardsFacing(int &x, int &y, int facing); - int getMoveTableSize(int *moveTable); - virtual bool lineIsPassable(int x, int y) = 0; - - static const int8 _addXPosTable[]; - static const int8 _addYPosTable[]; - - // save/load - int _gameToLoad; - - const char *getSavegameFilename(int num); - bool saveFileLoadable(int slot); - - struct SaveHeader { - Common::String description; - uint32 version; - byte gameID; - uint32 flags; - - bool originalSave; // savegame from original interpreter - bool oldHeader; // old scummvm save header - }; - - enum kReadSaveHeaderError { - kRSHENoError = 0, - kRSHEInvalidType = 1, - kRSHEInvalidVersion = 2, - kRSHEIoError = 3 - }; - - static kReadSaveHeaderError readSaveHeader(Common::InSaveFile *file, SaveHeader &header); - - Common::InSaveFile *openSaveForReading(const char *filename, SaveHeader &header); - Common::OutSaveFile *openSaveForWriting(const char *filename, const char *saveName) const; -}; - -} // End of namespace Kyra - -#endif - diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index c25af91bec..57f0dcc24a 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -23,7 +23,7 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_hof.h" #include "kyra/screen.h" #include "kyra/resource.h" @@ -49,11 +49,13 @@ const KyraEngine_v2::EngineDesc KyraEngine_HoF::_hofEngineDesc = { 8, // Animation script specific - 33 + 33, + + // Item specific + 175 }; KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEngine_v2(system, flags, _hofEngineDesc), _updateFunctor(this, &KyraEngine_HoF::update) { - _mouseSHPBuf = 0; _screen = 0; _text = 0; @@ -79,7 +81,7 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _oldTalkFile = -1; _currentTalkFile = 0; _lastSfxTrack = -1; - _handItemSet = -1; + _mouseState = -1; _unkHandleSceneChangeFlag = false; _pathfinderFlag = 0; _mouseX = _mouseY = 0; @@ -140,13 +142,14 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _menuDirectlyToLoad = false; _menu = 0; + _chatIsNote = false; + memset(&_npcScriptData, 0, sizeof(_npcScriptData)); } KyraEngine_HoF::~KyraEngine_HoF() { cleanup(); seq_uninit(); - delete [] _mouseSHPBuf; delete _screen; delete _text; delete _gui; @@ -157,29 +160,67 @@ KyraEngine_HoF::~KyraEngine_HoF() { if (_sequenceSoundList) { for (int i = 0; i < _sequenceSoundListSize; i++) { if (_sequenceSoundList[i]) - delete [] _sequenceSoundList[i]; + delete[] _sequenceSoundList[i]; } - delete [] _sequenceSoundList; + delete[] _sequenceSoundList; _sequenceSoundList = NULL; } if (_dlgBuffer) - delete [] _dlgBuffer; + delete[] _dlgBuffer; for (int i = 0; i < 19; i++) - delete [] _conversationState[i]; - delete [] _conversationState; + delete[] _conversationState[i]; + delete[] _conversationState; for (Common::Array<const TIMOpcode*>::iterator i = _timOpcodes.begin(); i != _timOpcodes.end(); ++i) delete *i; _timOpcodes.clear(); } +void KyraEngine_HoF::pauseEngineIntern(bool pause) { + KyraEngine_v2::pauseEngineIntern(pause); + + if (!pause) { + uint32 pausedTime = _system->getMillis() - _pauseStart; + _pauseStart = 0; + + // sequence player + // + // Timers in KyraEngine_HoF::seq_cmpFadeFrame() and KyraEngine_HoF::seq_animatedSubFrame() + // have been left out for now. I think we don't need them here. + + _seqStartTime += pausedTime; + _seqSubFrameStartTime += pausedTime; + _seqEndTime += pausedTime; + _seqSubFrameEndTimeInternal += pausedTime; + _seqWsaChatTimeout += pausedTime; + _seqWsaChatFrameTimeout += pausedTime; + + for (int x = 0; x < 10; x++) { + if (_activeText[x].duration != -1) + _activeText[x].startTime += pausedTime; + } + + for (int x = 0; x < 8; x++) { + if (_activeWSA[x].flags != -1) + _activeWSA[x].nextFrame += pausedTime; + } + + _nextIdleAnim += pausedTime; + + for (int x = 0; x < _itemAnimDataSize; x++) + _activeItemAnim[x].nextFrame += pausedTime; + + _tim->refreshTimersAfterPause(pausedTime); + } +} + int KyraEngine_HoF::init() { _screen = new Screen_HoF(this, _system); assert(_screen); _screen->setResolution(); - KyraEngine::init(); + KyraEngine_v1::init(); initStaticResource(); _debugger = new Debugger_HoF(this); @@ -218,11 +259,14 @@ int KyraEngine_HoF::init() { if (_flags.isDemo && !_flags.isTalkie) return 0; - _mouseSHPBuf = _res->fileData("PWGMOUSE.SHP", 0); - assert(_mouseSHPBuf); + _res->exists("PWGMOUSE.SHP", true); + uint8 *shapes = _res->fileData("PWGMOUSE.SHP", 0); + assert(shapes); for (int i = 0; i < 2; i++) - addShapeToPool(_screen->getPtrToShape(_mouseSHPBuf, i), i); + addShapeToPool(shapes, i, i); + + delete[] shapes; _screen->setMouseCursor(0, 0, getShapePtr(0)); return 0; @@ -280,10 +324,7 @@ void KyraEngine_HoF::startup() { allocAnimObjects(1, 10, 30); _screen->_curPage = 0; - delete [] _mouseSHPBuf; - _mouseSHPBuf = 0; - _gameShapes.clear(); memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable)); _gamePlayBuffer = new uint8[46080]; _unkBuf500Bytes = new uint8[500]; @@ -316,18 +357,16 @@ void KyraEngine_HoF::startup() { _screen->setShapePages(5, 3); - memset(&_mainCharacter, 0, sizeof(_mainCharacter)); _mainCharacter.height = 0x30; _mainCharacter.facing = 4; _mainCharacter.animFrame = 0x12; - memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); memset(_sceneAnims, 0, sizeof(_sceneAnims)); for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) - _sceneAnimMovie[i] = new WSAMovieV2(this, _screen); + _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen); memset(_wsaSlots, 0, sizeof(_wsaSlots)); for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) - _wsaSlots[i] = new WSAMovieV2(this, _screen); + _wsaSlots[i] = new WSAMovie_v2(this, _screen); _screen->_curPage = 0; @@ -448,7 +487,7 @@ void KyraEngine_HoF::runLoop() { update(); if (inputFlag == 198 || inputFlag == 199) { - _unk3 = _handItemSet; + _unk3 = _mouseState; handleInput(_mouseX, _mouseY); } @@ -567,7 +606,7 @@ bool KyraEngine_HoF::handleInputUnkSub(int x, int y) { if (y > 143 || _deathHandler > -1 || queryGameFlag(0x164)) return false; - if (_handItemSet <= -3 && findItem(_mainCharacter.sceneId, 13) >= 0) { + if (_mouseState <= -3 && findItem(_mainCharacter.sceneId, 13) >= 0) { updateCharFacing(); objectChat(getTableString(0xFC, _cCodeBuffer, 1), 0, 0x83, 0xFC); return true; @@ -722,17 +761,16 @@ void KyraEngine_HoF::updateMouse() { yOffset = 9; } - if (type != 0 && _handItemSet != type && _screen->isMouseVisible()) { - _mouseState = _handItemSet = type; + if (type != 0 && _mouseState != type && _screen->isMouseVisible()) { + _mouseState = type; _screen->hideMouse(); _screen->setMouseCursor(xOffset, yOffset, getShapePtr(shapeIndex)); _screen->showMouse(); } - if (type == 0 && _handItemSet != _itemInHand && _screen->isMouseVisible()) { + if (type == 0 && _mouseState != _itemInHand && _screen->isMouseVisible()) { if ((mouse.y > 145) || (mouse.x > 6 && mouse.x < 312 && mouse.y > 6 && mouse.y < 135)) { - _mouseState = 0; - _handItemSet = _itemInHand; + _mouseState = _itemInHand; _screen->hideMouse(); if (_itemInHand == -1) _screen->setMouseCursor(0, 0, getShapePtr(0)); @@ -743,44 +781,25 @@ void KyraEngine_HoF::updateMouse() { } } -void KyraEngine_HoF::delay(uint32 amount, bool updateGame, bool isMainLoop) { - uint32 start = _system->getMillis(); - do { - if (updateGame) { - if (_chatText) - updateWithText(); - else - update(); - } else { - updateInput(); - } - - if (amount > 0) - _system->delayMillis(amount > 10 ? 10 : amount); - } while (!skipFlag() && _system->getMillis() < start + amount && !_quitFlag); -} - void KyraEngine_HoF::cleanup() { - delete [] _inventoryButtons; _inventoryButtons = 0; + delete[] _inventoryButtons; _inventoryButtons = 0; - delete [] _gamePlayBuffer; _gamePlayBuffer = 0; - delete [] _unkBuf500Bytes; _unkBuf500Bytes = 0; - delete [] _unkBuf200kByte; _unkBuf200kByte = 0; + delete[] _gamePlayBuffer; _gamePlayBuffer = 0; + delete[] _unkBuf500Bytes; _unkBuf500Bytes = 0; + delete[] _unkBuf200kByte; _unkBuf200kByte = 0; freeSceneShapePtrs(); if (_optionsBuffer != _cCodeBuffer) - delete [] _optionsBuffer; + delete[] _optionsBuffer; _optionsBuffer = 0; - delete [] _cCodeBuffer; _cCodeBuffer = 0; - delete [] _chapterBuffer; _chapterBuffer = 0; + delete[] _cCodeBuffer; _cCodeBuffer = 0; + delete[] _chapterBuffer; _chapterBuffer = 0; - delete [] _talkObjectList; _talkObjectList = 0; - delete [] _shapeDescTable; _shapeDescTable = 0; + delete[] _talkObjectList; _talkObjectList = 0; + delete[] _shapeDescTable; _shapeDescTable = 0; - delete [] _gfxBackUpRect; _gfxBackUpRect = 0; - - delete [] _sceneList; _sceneList = 0; + delete[] _gfxBackUpRect; _gfxBackUpRect = 0; for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) { delete _sceneAnimMovie[i]; @@ -791,9 +810,11 @@ void KyraEngine_HoF::cleanup() { _wsaSlots[i] = 0; } for (int i = 0; i < ARRAYSIZE(_buttonShapes); ++i) { - delete [] _buttonShapes[i]; + delete[] _buttonShapes[i]; _buttonShapes[i] = 0; } + + _emc->unload(&_npcScriptData); } #pragma mark - Localization @@ -803,7 +824,7 @@ void KyraEngine_HoF::loadCCodeBuffer(const char *file) { strcpy(tempString, file); changeFileExtension(tempString); - delete [] _cCodeBuffer; + delete[] _cCodeBuffer; _cCodeBuffer = _res->fileData(tempString, 0); } @@ -812,7 +833,7 @@ void KyraEngine_HoF::loadOptionsBuffer(const char *file) { strcpy(tempString, file); changeFileExtension(tempString); - delete [] _optionsBuffer; + delete[] _optionsBuffer; _optionsBuffer = _res->fileData(tempString, 0); } @@ -827,7 +848,7 @@ void KyraEngine_HoF::loadChapterBuffer(int chapter) { strcpy(tempString, chapterFilenames[chapter-1]); changeFileExtension(tempString); - delete [] _chapterBuffer; + delete[] _chapterBuffer; _chapterBuffer = _res->fileData(tempString, 0); _currentChapter = chapter; } @@ -1008,7 +1029,7 @@ void KyraEngine_HoF::loadMouseShapes() { _screen->loadBitmap("_MOUSE.CSH", 3, 3, 0); for (int i = 0; i <= 8; ++i) - addShapeToPool(_screen->makeShapeCopy(_screen->getCPagePtr(3), i), i); + addShapeToPool(_screen->getCPagePtr(3), i, i); } void KyraEngine_HoF::loadItemShapes() { @@ -1033,7 +1054,7 @@ void KyraEngine_HoF::loadCharacterShapes(int shapes) { uint8 *data = _res->fileData(file, 0); for (int i = 9; i <= 32; ++i) addShapeToPool(data, i, i-9); - delete [] data; + delete[] data; _characterShapeFile = shapes; } @@ -1070,6 +1091,8 @@ void KyraEngine_HoF::runStartScript(int script, int unk1) { } void KyraEngine_HoF::loadNPCScript() { + _emc->unload(&_npcScriptData); + char filename[12]; strcpy(filename, "_NPC.EMC"); @@ -1382,7 +1405,7 @@ int KyraEngine_HoF::initAnimationShapes(uint8 *filedata) { void KyraEngine_HoF::uninitAnimationShapes(int count, uint8 *filedata) { for (int i = 0; i < count; ++i) remShapeFromPool(i+33); - delete [] filedata; + delete[] filedata; setNextIdleAnimTimer(); } @@ -1541,7 +1564,7 @@ void KyraEngine_HoF::snd_playSoundEffect(int track, int volume) { else if (_flags.platform == Common::kPlatformPC) // TODO ?? Maybe there is a way to let users select whether they want // voc, midi or adl sfx (even though it makes no sense to choose anything but voc). - KyraEngine::snd_playSoundEffect(track); + KyraEngine_v1::snd_playSoundEffect(track); } #pragma mark - @@ -1552,7 +1575,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run, int delayTime, in wsaFlags |= 2; if (!_invWsa.wsa) - _invWsa.wsa = new WSAMovieV2(this, _screen); + _invWsa.wsa = new WSAMovie_v2(this, _screen); if (!_invWsa.wsa->open(filename, wsaFlags, 0)) error("Couldn't open inventory WSA file '%s'", filename); @@ -1969,7 +1992,7 @@ void KyraEngine_HoF::playTim(const char *filename) { #pragma mark - void KyraEngine_HoF::registerDefaultSettings() { - KyraEngine::registerDefaultSettings(); + KyraEngine_v1::registerDefaultSettings(); // Most settings already have sensible defaults. This one, however, is // specific to the Kyra engine. @@ -2000,13 +2023,13 @@ void KyraEngine_HoF::writeSettings() { ConfMan.set("language", Common::getLanguageCode(_flags.lang)); - KyraEngine::writeSettings(); + KyraEngine_v1::writeSettings(); } void KyraEngine_HoF::readSettings() { int talkspeed = ConfMan.getInt("talkspeed"); _configTextspeed = (talkspeed*95)/255 + 2; - KyraEngine::readSettings(); + KyraEngine_v1::readSettings(); } } // end of namespace Kyra diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index 1e6c23331e..866dd55d16 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -97,22 +97,17 @@ enum kNestedSequencesDemo { kSequenceDemoDig }; -class WSAMovieV2; +class WSAMovie_v2; class KyraEngine_HoF; class TextDisplayer_HoF; struct TIM; -typedef int (KyraEngine_HoF::*SeqProc)(WSAMovieV2*, int, int, int); - -struct FrameControl { - uint16 index; - uint16 delay; -}; +typedef int (KyraEngine_HoF::*SeqProc)(WSAMovie_v2*, int, int, int); struct ActiveWSA { int16 flags; - WSAMovieV2 *movie; + WSAMovie_v2 *movie; uint16 startFrame; uint16 endFrame; uint16 frameDelay; @@ -179,17 +174,6 @@ struct ItemAnimData_v1 { const uint16 *frames; }; -struct ItemAnimData_v2 { - int16 itemIndex; - uint8 numFrames; - const FrameControl *frames; -}; - -struct ActiveItemAnim { - uint16 currentFrame; - uint32 nextFrame; -}; - class KyraEngine_HoF : public KyraEngine_v2 { friend class Debugger_HoF; friend class TextDisplayer_HoF; @@ -198,6 +182,8 @@ public: KyraEngine_HoF(OSystem *system, const GameFlags &flags); ~KyraEngine_HoF(); + void pauseEngineIntern(bool pause); + Screen *screen() { return _screen; } Screen_v2 *screen_v2() const { return _screen; } GUI_v2 *gui_v2() const { return _gui; } @@ -209,52 +195,52 @@ protected: // intro/outro void seq_playSequences(int startSeq, int endSeq = -1); - int seq_introWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introTitle(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introOverview(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introLibrary(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introHand(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introPoint(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introZanfaun(WSAMovieV2 *wsaObj, int x, int y, int frm); - - int seq_introOver1(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introOver2(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introForest(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introDragon(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introDarm(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introLibrary2(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introMarco(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introHand1a(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introHand1b(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introHand1c(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introHand2(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_introHand3(WSAMovieV2 *wsaObj, int x, int y, int frm); - - int seq_finaleFunters(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFerb(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFish(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFheep(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFarmer(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFuards(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFirates(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_finaleFrash(WSAMovieV2 *wsaObj, int x, int y, int frm); - - int seq_finaleFiggle(WSAMovieV2 *wsaObj, int x, int y, int frm); - - int seq_demoVirgin(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoTitle(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoHill(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoOuthome(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoWharf(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoDinob(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoFisher(WSAMovieV2 *wsaObj, int x, int y, int frm); - - int seq_demoWharf2(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoDinob2(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoWater(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoBail(WSAMovieV2 *wsaObj, int x, int y, int frm); - int seq_demoDig(WSAMovieV2 *wsaObj, int x, int y, int frm); + int seq_introWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int seq_introOver1(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introOver2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introForest(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introHand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int seq_finaleFiggle(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int seq_demoVirgin(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoHill(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoOuthome(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoWharf(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoDinob(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoFisher(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int seq_demoWharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoDinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoWater(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoBail(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm); void seq_sequenceCommand(int command); void seq_loadNestedSequence(int wsaNum, int seqNum); @@ -275,7 +261,7 @@ protected: char *seq_preprocessString(const char *str, int width); void seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor); void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, - WSAMovieV2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); + WSAMovie_v2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); void seq_finaleActorScreen(); void seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData = 0, const char *const *specialData = 0); void seq_scrollPage(); @@ -291,8 +277,6 @@ protected: TextDisplayer_HoF *_text; TIMInterpreter *_tim; - uint8 *_mouseSHPBuf; - static const int8 _dosTrackMap[]; static const int _dosTrackMapSize; @@ -329,8 +313,6 @@ protected: void dinoRide(); - int _mouseState; - void handleInput(int x, int y); bool handleInputUnkSub(int x, int y); @@ -350,7 +332,7 @@ protected: uint8 *_sceneShapeTable[50]; - WSAMovieV2 *_wsaSlots[10]; + WSAMovie_v2 *_wsaSlots[10]; void freeSceneShapePtrs(); @@ -675,9 +657,6 @@ protected: void setWalkspeed(uint8 speed); - // delay - void delay(uint32 millis, bool updateGame = false, bool isMainLoop = false); - // ingame static sequence handling void seq_makeBookOrCauldronAppear(int type); void seq_makeBookAppear(); @@ -690,7 +669,7 @@ protected: int delay; bool running; uint32 timer; - WSAMovieV2 *wsa; + WSAMovie_v2 *wsa; } _invWsa; // TODO: move inside KyraEngine_HoF::InventoryWsa? @@ -732,7 +711,6 @@ protected: int o2_wipeDownMouseItem(EMCState *script); int o2_getElapsedSecs(EMCState *script); int o2_getTimerDelay(EMCState *script); - //int o2_playSoundEffect(EMCState *script); int o2_delaySecs(EMCState *script); int o2_setTimerDelay(EMCState *script); int o2_setScaleTableItem(EMCState *script); @@ -759,17 +737,14 @@ protected: int o2_setLayerFlag(EMCState *script); int o2_setZanthiaPos(EMCState *script); int o2_loadMusicTrack(EMCState *script); - int o2_playSoundEffect(EMCState *script); int o2_setSceneAnimPos(EMCState *script); - int o2_blockInRegion(EMCState *script); - int o2_blockOutRegion(EMCState *script); int o2_setCauldronState(EMCState *script); int o2_showItemString(EMCState *script); int o2_isAnySoundPlaying(EMCState *script); int o2_setDrawNoShapeFlag(EMCState *script); int o2_setRunFlag(EMCState *script); int o2_showLetter(EMCState *script); - int o2_fillRect(EMCState *script); + int o2_playFireflyScore(EMCState *script); int o2_encodeShape(EMCState *script); int o2_defineSceneAnim(EMCState *script); int o2_updateSceneAnim(EMCState *script); @@ -805,7 +780,7 @@ protected: int o2_updateTwoSceneAnims(EMCState *script); int o2_getRainbowRoomData(EMCState *script); int o2_drawSceneShapeEx(EMCState *script); - int o2_getBoolFromStack(EMCState *script); + int o2_midiSoundFadeout(EMCState *script); int o2_getSfxDriver(EMCState *script); int o2_getVocSupport(EMCState *script); int o2_getMusicDriver(EMCState *script); @@ -876,14 +851,19 @@ protected: static const uint8 _seqTextColorPresets[]; char *_seqProcessedString; - WSAMovieV2 *_seqWsa; + WSAMovie_v2 *_seqWsa; bool _abortIntroFlag; int _menuChoice; uint32 _seqFrameDelay; uint32 _seqStartTime; + uint32 _seqSubFrameStartTime; uint32 _seqEndTime; + uint32 _seqSubFrameEndTimeInternal; + uint32 _seqWsaChatTimeout; + uint32 _seqWsaChatFrameTimeout; + int _seqFrameCounter; int _seqScrollTextCounter; int _seqWsaCurrentFrame; diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp new file mode 100644 index 0000000000..c852f6e3ee --- /dev/null +++ b/engines/kyra/kyra_lok.cpp @@ -0,0 +1,1044 @@ +/* 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 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 "kyra/kyra_lok.h" + +#include "common/file.h" +#include "common/events.h" +#include "common/system.h" +#include "common/savefile.h" + +#include "gui/message.h" + +#include "kyra/resource.h" +#include "kyra/screen.h" +#include "kyra/script.h" +#include "kyra/seqplayer.h" +#include "kyra/sound.h" +#include "kyra/sprites.h" +#include "kyra/wsamovie.h" +#include "kyra/animator_lok.h" +#include "kyra/text.h" +#include "kyra/debugger.h" +#include "kyra/timer.h" + +namespace Kyra { + +KyraEngine_LoK::KyraEngine_LoK(OSystem *system, const GameFlags &flags) + : KyraEngine_v1(system, flags) { + _skipFlag = false; + + _seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm = + _seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 = + _seq_Demo4 = 0; + + _seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0; + _seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0; + + _roomFilenameTable = _characterImageTable = 0; + _roomFilenameTableSize = _characterImageTableSize = 0; + _itemList = _takenList = _placedList = _droppedList = _noDropList = 0; + _itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0; + _putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0; + _putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0; + _thePoison = _fluteString = _wispJewelStrings = _magicJewelString = _flaskFull = _fullFlask = 0; + _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0; + _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0; + + _defaultShapeTable = 0; + _healingShapeTable = _healingShape2Table = 0; + _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0; + _posionDeathShapeTable = _fluteAnimShapeTable = 0; + _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0; + _winterScrollTable = _winterScroll1Table = _winterScroll2Table = 0; + _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0; + _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0; + _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0; + memset(&_specialPalettes, 0, sizeof(_specialPalettes)); + _sprites = 0; + _animator = 0; + _seq = 0; + _characterList = 0; + _movFacingTable = 0; + _buttonData = 0; + _buttonDataListPtr = 0; + memset(_shapes, 0, sizeof(_shapes)); + memset(_movieObjects, 0, sizeof(_movieObjects)); + _finalA = _finalB = _finalC = 0; + _endSequenceBackUpRect = 0; + memset(_panPagesTable, 0, sizeof(_panPagesTable)); + memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); + _currHeadShape = 0; + _speechPlayTime = 0; + + memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp)); +} + +KyraEngine_LoK::~KyraEngine_LoK() { + for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) { + if (_movieObjects[i]) + _movieObjects[i]->close(); + delete _movieObjects[i]; + _movieObjects[i] = 0; + } + + closeFinalWsa(); + if (_emc) { + _emc->unload(&_npcScriptData); + _emc->unload(&_scriptClickData); + } + + Common::clearAllSpecialDebugLevels(); + + delete _screen; + delete _sprites; + delete _animator; + delete _seq; + + delete[] _characterList; + + delete[] _movFacingTable; + + delete[] _gui->_scrollUpButton.data0ShapePtr; + delete[] _gui->_scrollUpButton.data1ShapePtr; + delete[] _gui->_scrollUpButton.data2ShapePtr; + delete[] _gui->_scrollDownButton.data0ShapePtr; + delete[] _gui->_scrollDownButton.data1ShapePtr; + delete[] _gui->_scrollDownButton.data2ShapePtr; + + delete[] _buttonData; + delete[] _buttonDataListPtr; + + delete _gui; + + delete[] _itemBkgBackUp[0]; + delete[] _itemBkgBackUp[1]; + + for (int i = 0; i < ARRAYSIZE(_shapes); ++i) { + if (_shapes[i] != 0) { + delete[] _shapes[i]; + for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) { + if (_shapes[i2] == _shapes[i] && i2 != i) { + _shapes[i2] = 0; + } + } + _shapes[i] = 0; + } + } + + for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) + delete[] _sceneAnimTable[i]; +} + +int KyraEngine_LoK::init() { + _screen = new Screen_LoK(this, _system); + assert(_screen); + _screen->setResolution(); + + KyraEngine_v1::init(); + + _sprites = new Sprites(this, _system); + assert(_sprites); + _seq = new SeqPlayer(this, _system); + assert(_seq); + _animator = new Animator_LoK(this, _system); + assert(_animator); + _animator->init(5, 11, 12); + assert(*_animator); + _text = new TextDisplayer(this, screen()); + assert(_text); + _gui = new GUI_LoK(this, _screen); + assert(_gui); + + initStaticResource(); + + _sound->setSoundList(&_soundData[kMusicIntro]); + + _trackMap = _dosTrackMap; + _trackMapSize = _dosTrackMapSize; + + if (!_sound->init()) + error("Couldn't init sound"); + + _sound->loadSoundFile(0); + + setupButtonData(); + + _paletteChanged = 1; + _currentCharacter = 0; + _characterList = new Character[11]; + assert(_characterList); + memset(_characterList, 0, sizeof(Character)*11); + + for (int i = 0; i < 11; ++i) + memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems)); + + _characterList[0].sceneId = 5; + _characterList[0].height = 48; + _characterList[0].facing = 3; + _characterList[0].currentAnimFrame = 7; + + memset(&_npcScriptData, 0, sizeof(EMCData)); + memset(&_scriptClickData, 0, sizeof(EMCData)); + + memset(&_npcScript, 0, sizeof(EMCState)); + memset(&_scriptMain, 0, sizeof(EMCState)); + memset(&_scriptClick, 0, sizeof(EMCState)); + + _debugger = new Debugger_LoK(this); + assert(_debugger); + memset(_shapes, 0, sizeof(_shapes)); + + for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) + _movieObjects[i] = createWSAMovie(); + + memset(_flagsTable, 0, sizeof(_flagsTable)); + + _abortWalkFlag = false; + _abortWalkFlag2 = false; + _talkingCharNum = -1; + _charSayUnk3 = -1; + memset(_currSentenceColor, 0, 3); + _startSentencePalIndex = -1; + _fadeText = false; + + _cauldronState = 0; + _crystalState[0] = _crystalState[1] = -1; + + _brandonStatusBit = 0; + _brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10; + _brandonPosX = _brandonPosY = -1; + _poisonDeathCounter = 0; + + memset(_itemTable, 0, sizeof(_itemTable)); + memset(_exitList, 0xFFFF, sizeof(_exitList)); + _exitListPtr = 0; + _pathfinderFlag = _pathfinderFlag2 = 0; + _lastFindWayRet = 0; + _sceneChangeState = _loopFlag2 = 0; + + _movFacingTable = new int[150]; + assert(_movFacingTable); + _movFacingTable[0] = 8; + + _skipFlag = false; + + _marbleVaseItem = -1; + memset(_foyerItemTable, -1, sizeof(_foyerItemTable)); + _itemInHand = -1; + _handleInput = false; + + _currentRoom = 0xFFFF; + _scenePhasingFlag = 0; + _lastProcessedItem = 0; + _lastProcessedItemHeight = 16; + + _unkScreenVar1 = 1; + _unkScreenVar2 = 0; + _unkScreenVar3 = 0; + _unkAmuletVar = 0; + + _endSequenceNeedLoading = 1; + _malcolmFlag = 0; + _beadStateVar = 0; + _endSequenceSkipFlag = 0; + _unkEndSeqVar2 = 0; + _endSequenceBackUpRect = 0; + _unkEndSeqVar4 = 0; + _unkEndSeqVar5 = 0; + _lastDisplayedPanPage = 0; + memset(_panPagesTable, 0, sizeof(_panPagesTable)); + _finalA = _finalB = _finalC = 0; + memset(&_kyragemFadingState, 0, sizeof(_kyragemFadingState)); + _kyragemFadingState.gOffset = 0x13; + _kyragemFadingState.bOffset = 0x13; + + _mousePressFlag = false; + + _menuDirectlyToLoad = false; + + _lastMusicCommand = 0; + + return 0; +} + +int KyraEngine_LoK::go() { + if (_res->getFileSize("6.FNT")) + _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); + _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); + _screen->setScreenDim(0); + + _abortIntroFlag = false; + + if (_flags.isDemo) { + seq_demo(); + } else { + setGameFlag(0xF3); + setGameFlag(0xFD); + if (_gameToLoad == -1) { + setGameFlag(0xEF); + seq_intro(); + if (_quitFlag) + return 0; + if (_skipIntroFlag && _abortIntroFlag) + resetGameFlag(0xEF); + } + startup(); + resetGameFlag(0xEF); + mainLoop(); + } + return 0; +} + + +void KyraEngine_LoK::startup() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::startup()"); + static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 }; + _screen->setTextColorMap(colorMap); + _sound->setSoundList(&_soundData[kMusicIngame]); + _sound->loadSoundFile(0); +// _screen->setFont(Screen::FID_6_FNT); + _screen->setAnimBlockPtr(3750); + memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); + loadMouseShapes(); + _currentCharacter = &_characterList[0]; + for (int i = 1; i < 5; ++i) + _animator->setCharacterDefaultFrame(i); + for (int i = 5; i <= 10; ++i) + setCharactersPositions(i); + _animator->setCharactersHeight(); + resetBrandonPoisonFlags(); + _screen->_curPage = 0; + // XXX + for (int i = 0; i < 12; ++i) { + int size = _screen->getRectSize(3, 24); + _shapes[361+i] = new byte[size]; + } + + _itemBkgBackUp[0] = new uint8[_screen->getRectSize(3, 24)]; + memset(_itemBkgBackUp[0], 0, _screen->getRectSize(3, 24)); + _itemBkgBackUp[1] = new uint8[_screen->getRectSize(4, 32)]; + memset(_itemBkgBackUp[1], 0, _screen->getRectSize(4, 32)); + + for (int i = 0; i < _roomTableSize; ++i) { + for (int item = 0; item < 12; ++item) { + _roomTable[i].itemsTable[item] = 0xFF; + _roomTable[i].itemsXPos[item] = 0xFFFF; + _roomTable[i].itemsYPos[item] = 0xFF; + _roomTable[i].needInit[item] = 0; + } + } + + loadCharacterShapes(); + loadSpecialEffectShapes(); + loadItems(); + loadButtonShapes(); + initMainButtonList(); + loadMainScreen(); + _screen->loadPalette("PALETTE.COL", _screen->_currentPalette); + + // XXX + _animator->initAnimStateList(); + setCharactersInDefaultScene(); + + if (!_emc->load("_STARTUP.EMC", &_npcScriptData, &_opcodes)) + error("Could not load \"_STARTUP.EMC\" script"); + _emc->init(&_scriptMain, &_npcScriptData); + + if (!_emc->start(&_scriptMain, 0)) + error("Could not start script function 0 of script \"_STARTUP.EMC\""); + + while (_emc->isValid(&_scriptMain)) + _emc->run(&_scriptMain); + + _emc->unload(&_npcScriptData); + + if (!_emc->load("_NPC.EMC", &_npcScriptData, &_opcodes)) + error("Could not load \"_NPC.EMC\" script"); + + snd_playTheme(1, -1); + if (_gameToLoad == -1) { + enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); + if (_abortIntroFlag && _skipIntroFlag) { + _menuDirectlyToLoad = true; + _screen->setMouseCursor(1, 1, _shapes[0]); + _screen->showMouse(); + _gui->buttonMenuCallback(0); + _menuDirectlyToLoad = false; + } else + saveGame(getSavegameFilename(0), "New game"); + } else { + _screen->setFont(Screen::FID_8_FNT); + loadGame(getSavegameFilename(_gameToLoad)); + _gameToLoad = -1; + } +} + +void KyraEngine_LoK::mainLoop() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::mainLoop()"); + + while (!_quitFlag) { + int32 frameTime = (int32)_system->getMillis(); + _skipFlag = false; + + if (_currentCharacter->sceneId == 210) { + updateKyragemFading(); + if (seq_playEnd() && _deathHandler != 8) + break; + } + + if (_deathHandler != -1) { + snd_playWanderScoreViaMap(0, 1); + snd_playSoundEffect(49); + _screen->hideMouse(); + _screen->setMouseCursor(1, 1, _shapes[0]); + removeHandItem(); + _screen->showMouse(); + _gui->buttonMenuCallback(0); + _deathHandler = -1; + } + + if ((_brandonStatusBit & 2) && _brandonStatusBit0x02Flag) + _animator->animRefreshNPC(0); + + if ((_brandonStatusBit & 0x20) && _brandonStatusBit0x20Flag) { + _animator->animRefreshNPC(0); + _brandonStatusBit0x20Flag = 0; + } + + _screen->showMouse(); + + _gui->processButtonList(_buttonList, 0, 0); + updateMousePointer(); + _timer->update(); + updateTextFade(); + + _handleInput = true; + delay((frameTime + _gameSpeed) - _system->getMillis(), true, true); + _handleInput = false; + + _sound->process(); + } +} + +void KyraEngine_LoK::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { + while (_system->getMillis() < timestamp && !_quitFlag) { + if (updateTimers) + _timer->update(); + + if (timestamp - _system->getMillis() >= 10) + delay(10, update, isMainLoop); + } +} + +void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { + Common::Event event; + + uint32 start = _system->getMillis(); + do { + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' && + (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && isMainLoop) { + const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990); + + if (event.kbd.flags == Common::KBD_CTRL) + loadGame(saveLoadSlot); + else { + char savegameName[14]; + sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); + saveGame(saveLoadSlot, savegameName); + } + } else if (event.kbd.flags == Common::KBD_CTRL) { + if (event.kbd.keycode == 'd') + _debugger->attach(); + else if (event.kbd.keycode == 'q') + _quitFlag = true; + } else if (event.kbd.keycode == '.') { + _skipFlag = true; + } else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) { + _abortIntroFlag = true; + _skipFlag = true; + } + + break; + case Common::EVENT_MOUSEMOVE: + _animator->_updateScreen = true; + break; + case Common::EVENT_QUIT: + quitGame(); + break; + case Common::EVENT_LBUTTONDOWN: + _mousePressFlag = true; + break; + case Common::EVENT_LBUTTONUP: + _mousePressFlag = false; + + if (_abortWalkFlag2) + _abortWalkFlag = true; + + if (_handleInput) { + _handleInput = false; + processInput(); + _handleInput = true; + } else + _skipFlag = true; + + break; + default: + break; + } + } + + if (_debugger->isAttached()) + _debugger->onFrame(); + + if (update) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + updateTextFade(); + updateMousePointer(); + } + + if (_currentCharacter && _currentCharacter->sceneId == 210 && update) + updateKyragemFading(); + + if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) + _skipFlag = false; + + if (amount > 0 && !_skipFlag && !_quitFlag) + _system->delayMillis(10); + + if (_skipFlag) + _sound->voiceStop(); + } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag); +} + +void KyraEngine_LoK::waitForEvent() { + bool finished = false; + Common::Event event; + + while (!finished && !_quitFlag) { + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + finished = true; + break; + case Common::EVENT_QUIT: + quitGame(); + break; + case Common::EVENT_LBUTTONDOWN: + finished = true; + _skipFlag = true; + break; + default: + break; + } + } + + if (_debugger->isAttached()) + _debugger->onFrame(); + + _system->delayMillis(10); + } +} + +void KyraEngine_LoK::delayWithTicks(int ticks) { + uint32 nextTime = _system->getMillis() + ticks * _tickLength; + + while (_system->getMillis() < nextTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + + if (_currentCharacter->sceneId == 210) { + updateKyragemFading(); + seq_playEnd(); + } + + if (_skipFlag) + break; + + if (nextTime - _system->getMillis() >= 10) + delay(10); + } +} + +#pragma mark - +#pragma mark - Animation/shape specific code +#pragma mark - + +void KyraEngine_LoK::setupShapes123(const Shape *shapeTable, int endShape, int flags) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setupShapes123(%p, %d, %d)", (const void *)shapeTable, endShape, flags); + + for (int i = 123; i <= 172; ++i) + _shapes[i] = 0; + + uint8 curImage = 0xFF; + int curPageBackUp = _screen->_curPage; + _screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff + int shapeFlags = 2; + if (flags) + shapeFlags = 3; + for (int i = 123; i < 123+endShape; ++i) { + uint8 newImage = shapeTable[i-123].imageIndex; + if (newImage != curImage && newImage != 0xFF) { + assert(_characterImageTable); + _screen->loadBitmap(_characterImageTable[newImage], 8, 8, 0); + curImage = newImage; + } + _shapes[i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags); + assert(i-7 < _defaultShapeTableSize); + _defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset; + _defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset; + _defaultShapeTable[i-7].w = shapeTable[i-123].w; + _defaultShapeTable[i-7].h = shapeTable[i-123].h; + } + _screen->_curPage = curPageBackUp; +} + +void KyraEngine_LoK::freeShapes123() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::freeShapes123()"); + + for (int i = 123; i <= 172; ++i) { + delete[] _shapes[i]; + _shapes[i] = 0; + } +} + +#pragma mark - +#pragma mark - Misc stuff +#pragma mark - + +Movie *KyraEngine_LoK::createWSAMovie() { + if (_flags.platform == Common::kPlatformAmiga) + return new WSAMovieAmiga(this); + + return new WSAMovie_v1(this); +} + +void KyraEngine_LoK::setBrandonPoisonFlags(int reset) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setBrandonPoisonFlags(%d)", reset); + _brandonStatusBit |= 1; + + if (reset) + _poisonDeathCounter = 0; + + for (int i = 0; i < 0x100; ++i) + _brandonPoisonFlagsGFX[i] = i; + + _brandonPoisonFlagsGFX[0x99] = 0x34; + _brandonPoisonFlagsGFX[0x9A] = 0x35; + _brandonPoisonFlagsGFX[0x9B] = 0x37; + _brandonPoisonFlagsGFX[0x9C] = 0x38; + _brandonPoisonFlagsGFX[0x9D] = 0x2B; +} + +void KyraEngine_LoK::resetBrandonPoisonFlags() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::resetBrandonPoisonFlags()"); + _brandonStatusBit = 0; + + for (int i = 0; i < 0x100; ++i) + _brandonPoisonFlagsGFX[i] = i; +} + +#pragma mark - +#pragma mark - Input +#pragma mark - + +void KyraEngine_LoK::processInput() { + Common::Point mouse = getMousePos(); + int xpos = mouse.x; + int ypos = mouse.y; + + debugC(9, kDebugLevelMain, "KyraEngine_LoK::processInput(%d, %d)", xpos, ypos); + _abortWalkFlag2 = false; + + if (processInputHelper(xpos, ypos)) + return; + + uint8 item = findItemAtPos(xpos, ypos); + if (item == 0xFF) { + _changedScene = false; + int handled = clickEventHandler(xpos, ypos); + if (_changedScene || handled) + return; + } + + // XXX _deathHandler specific + if (ypos <= 158) { + uint16 exit = 0xFFFF; + if (xpos < 12) { + exit = _walkBlockWest; + } else if (xpos >= 308) { + exit = _walkBlockEast; + } else if (ypos >= 136) { + exit = _walkBlockSouth; + } else if (ypos < 12) { + exit = _walkBlockNorth; + } + + if (exit != 0xFFFF) { + _abortWalkFlag2 = true; + handleSceneChange(xpos, ypos, 1, 1); + _abortWalkFlag2 = false; + return; + } else { + int script = checkForNPCScriptRun(xpos, ypos); + if (script >= 0) { + runNpcScript(script); + return; + } + if (_itemInHand != -1) { + if (ypos < 155) { + if (hasClickedOnExit(xpos, ypos)) { + _abortWalkFlag2 = true; + handleSceneChange(xpos, ypos, 1, 1); + _abortWalkFlag2 = false; + return; + } + dropItem(0, _itemInHand, xpos, ypos, 1); + } + } else { + if (ypos <= 155) { + _abortWalkFlag2 = true; + handleSceneChange(xpos, ypos, 1, 1); + _abortWalkFlag2 = false; + } + } + } + } +} + +int KyraEngine_LoK::processInputHelper(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::processInputHelper(%d, %d)", xpos, ypos); + uint8 item = findItemAtPos(xpos, ypos); + if (item != 0xFF) { + if (_itemInHand == -1) { + _screen->hideMouse(); + _animator->animRemoveGameItem(item); + snd_playSoundEffect(53); + assert(_currentCharacter->sceneId < _roomTableSize); + Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; + int item2 = currentRoom->itemsTable[item]; + currentRoom->itemsTable[item] = 0xFF; + setMouseItem(item2); + assert(_itemList && _takenList); + updateSentenceCommand(_itemList[item2], _takenList[0], 179); + _itemInHand = item2; + _screen->showMouse(); + clickEventHandler2(); + return 1; + } else { + exchangeItemWithMouseItem(_currentCharacter->sceneId, item); + return 1; + } + } + return 0; +} + +int KyraEngine_LoK::clickEventHandler(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::clickEventHandler(%d, %d)", xpos, ypos); + _emc->init(&_scriptClick, &_scriptClickData); + _scriptClick.regs[1] = xpos; + _scriptClick.regs[2] = ypos; + _scriptClick.regs[3] = 0; + _scriptClick.regs[4] = _itemInHand; + _emc->start(&_scriptClick, 1); + + while (_emc->isValid(&_scriptClick)) + _emc->run(&_scriptClick); + + return _scriptClick.regs[3]; +} + +void KyraEngine_LoK::updateMousePointer(bool forceUpdate) { + int shape = 0; + + int newMouseState = 0; + int newX = 0; + int newY = 0; + Common::Point mouse = getMousePos(); + if (mouse.y <= 158) { + if (mouse.x >= 12) { + if (mouse.x >= 308) { + if (_walkBlockEast == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -5; + shape = 3; + newX = 7; + newY = 5; + } + } else if (mouse.y >= 136) { + if (_walkBlockSouth == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -4; + shape = 4; + newX = 5; + newY = 7; + } + } else if (mouse.y < 12) { + if (_walkBlockNorth == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -6; + shape = 2; + newX = 5; + newY = 1; + } + } + } else { + if (_walkBlockWest == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -3; + newX = 1; + newY = shape = 5; + } + } + } + + if (mouse.x >= _entranceMouseCursorTracks[0] && mouse.y >= _entranceMouseCursorTracks[1] + && mouse.x <= _entranceMouseCursorTracks[2] && mouse.y <= _entranceMouseCursorTracks[3]) { + switch (_entranceMouseCursorTracks[4]) { + case 0: + newMouseState = -6; + shape = 2; + newX = 5; + newY = 1; + break; + + case 2: + newMouseState = -5; + shape = 3; + newX = 7; + newY = 5; + break; + + case 4: + newMouseState = -4; + shape = 4; + newX = 5; + newY = 7; + break; + + case 6: + newMouseState = -3; + shape = 5; + newX = 1; + newY = 5; + break; + + default: + break; + } + } + + if (newMouseState == -2) { + shape = 6; + newX = 4; + newY = 4; + } + + if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) { + _mouseState = newMouseState; + _screen->hideMouse(); + _screen->setMouseCursor(newX, newY, _shapes[shape]); + _screen->showMouse(); + } + + if (!newMouseState) { + if (_mouseState != _itemInHand || forceUpdate) { + if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) { + _mouseState = _itemInHand; + _screen->hideMouse(); + if (_itemInHand == -1) + _screen->setMouseCursor(1, 1, _shapes[0]); + else + _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]); + _screen->showMouse(); + } + } + } +} + +bool KyraEngine_LoK::hasClickedOnExit(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::hasClickedOnExit(%d, %d)", xpos, ypos); + if (xpos < 16 || xpos >= 304) + return true; + + if (ypos < 8) + return true; + + if (ypos < 136 || ypos > 155) + return false; + + return true; +} + +void KyraEngine_LoK::clickEventHandler2() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::clickEventHandler2()"); + + Common::Point mouse = getMousePos(); + + _emc->init(&_scriptClick, &_scriptClickData); + _scriptClick.regs[0] = _currentCharacter->sceneId; + _scriptClick.regs[1] = mouse.x; + _scriptClick.regs[2] = mouse.y; + _scriptClick.regs[4] = _itemInHand; + _emc->start(&_scriptClick, 6); + + while (_emc->isValid(&_scriptClick)) + _emc->run(&_scriptClick); +} + +int KyraEngine_LoK::checkForNPCScriptRun(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::checkForNPCScriptRun(%d, %d)", xpos, ypos); + int returnValue = -1; + const Character *currentChar = _currentCharacter; + int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0; + + int scaleFactor = _scaleTable[currentChar->y1]; + int addX = (((scaleFactor*8)*3)>>8)>>1; + int addY = ((scaleFactor*3)<<4)>>8; + + charLeft = currentChar->x1 - addX; + charRight = currentChar->x1 + addX; + charTop = currentChar->y1 - addY; + charBottom = currentChar->y1; + + if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos) + return 0; + + if (xpos > 304 || xpos < 16) + return -1; + + for (int i = 1; i < 5; ++i) { + currentChar = &_characterList[i]; + + if (currentChar->sceneId != _currentCharacter->sceneId) + continue; + + charLeft = currentChar->x1 - 12; + charRight = currentChar->x1 + 11; + charTop = currentChar->y1 - 48; + // if (!i) + // charBottom = currentChar->y2 - 16; + // else + charBottom = currentChar->y1; + + if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos) + continue; + + if (returnValue != -1) { + if (currentChar->y1 >= _characterList[returnValue].y1) + returnValue = i; + } else { + returnValue = i; + } + } + + return returnValue; +} + +void KyraEngine_LoK::runNpcScript(int func) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::runNpcScript(%d)", func); + _emc->init(&_npcScript, &_npcScriptData); + _emc->start(&_npcScript, func); + _npcScript.regs[0] = _currentCharacter->sceneId; + _npcScript.regs[4] = _itemInHand; + _npcScript.regs[5] = func; + + while (_emc->isValid(&_npcScript)) + _emc->run(&_npcScript); +} + +void KyraEngine_LoK::checkAmuletAnimFlags() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::checkSpecialAnimFlags()"); + + if (_brandonStatusBit & 2) { + seq_makeBrandonNormal2(); + _timer->setCountdown(19, 300); + } + + if (_brandonStatusBit & 0x20) { + seq_makeBrandonNormal(); + _timer->setCountdown(19, 300); + } +} + +#pragma mark - + +void KyraEngine_LoK::registerDefaultSettings() { + KyraEngine_v1::registerDefaultSettings(); + + // Most settings already have sensible defaults. This one, however, is + // specific to the Kyra engine. + ConfMan.registerDefault("walkspeed", 2); +} + +void KyraEngine_LoK::readSettings() { + int talkspeed = ConfMan.getInt("talkspeed"); + + // The default talk speed is 60. This should be mapped to "Normal". + + if (talkspeed == 0) + _configTextspeed = 3; // Clickable + if (talkspeed <= 50) + _configTextspeed = 0; // Slow + else if (talkspeed <= 150) + _configTextspeed = 1; // Normal + else + _configTextspeed = 2; // Fast + + KyraEngine_v1::readSettings(); +} + +void KyraEngine_LoK::writeSettings() { + int talkspeed; + + switch (_configTextspeed) { + case 0: // Slow + talkspeed = 1; + break; + case 1: // Normal + talkspeed = 60; + break; + case 2: // Fast + talkspeed = 255; + break; + default: // Clickable + talkspeed = 0; + break; + } + + ConfMan.setInt("talkspeed", talkspeed); + + KyraEngine_v1::writeSettings(); +} + +} // end of namespace Kyra diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h new file mode 100644 index 0000000000..cb3062847e --- /dev/null +++ b/engines/kyra/kyra_lok.h @@ -0,0 +1,806 @@ +/* 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 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$ + * + */ + +#ifndef KYRA_KYRA_LOK_H +#define KYRA_KYRA_LOK_H + +#include "kyra/kyra_v1.h" +#include "kyra/script.h" +#include "kyra/screen_lok.h" +#include "kyra/gui_lok.h" + +namespace Kyra { + +class Movie; +class SoundDigital; +class SeqPlayer; +class Sprites; +class Animator_LoK; +class TextDisplayer; +class KyraEngine_LoK; + +struct Character { + uint16 sceneId; + uint8 height; + uint8 facing; + uint16 currentAnimFrame; + uint8 inventoryItems[10]; + int16 x1, y1, x2, y2; +}; + +struct Shape { + uint8 imageIndex; + int8 xOffset, yOffset; + uint8 x, y, w, h; +}; + +struct Room { + uint8 nameIndex; + uint16 northExit; + uint16 eastExit; + uint16 southExit; + uint16 westExit; + uint8 itemsTable[12]; + uint16 itemsXPos[12]; + uint8 itemsYPos[12]; + uint8 needInit[12]; +}; + +struct Item { + uint8 unk1; + uint8 height; + uint8 unk2; + uint8 unk3; +}; + +struct SeqLoop { + const uint8 *ptr; + uint16 count; +}; + +struct SceneExits { + uint16 northXPos; + uint8 northYPos; + uint16 eastXPos; + uint8 eastYPos; + uint16 southXPos; + uint8 southYPos; + uint16 westXPos; + uint8 westYPos; +}; + +struct BeadState { + int16 x; + int16 y; + int16 width; + int16 height; + int16 dstX; + int16 dstY; + int16 width2; + int16 unk8; + int16 unk9; + int16 tableIndex; +}; + +class KyraEngine_LoK : public KyraEngine_v1 { + friend class MusicPlayer; + friend class Debugger_LoK; + friend class Animator_LoK; + friend class GUI_LoK; +public: + KyraEngine_LoK(OSystem *system, const GameFlags &flags); + ~KyraEngine_LoK(); + + //TODO: proper extended implementation of KyraEngine_v1::pauseEngineIntern. + // _sprites and _seqplayer should be paused here too, to avoid some animation glitches, + // also parts of the hardcoded Malcolm fight might need some special handling. + + Screen *screen() { return _screen; } + Animator_LoK *animator() { return _animator; } + virtual Movie *createWSAMovie(); + + uint8 **shapes() { return _shapes; } + Character *currentCharacter() { return _currentCharacter; } + Character *characterList() { return _characterList; } + uint16 brandonStatus() { return _brandonStatusBit; } + + // TODO: remove me with workaround in animator.cpp l209 + uint16 getScene() { return _currentRoom; } + + int _paletteChanged; + int16 _northExitHeight; + + typedef void (KyraEngine_LoK::*IntroProc)(); + + // static data access + const char * const*seqWSATable() { return _seq_WSATable; } + const char * const*seqCPSTable() { return _seq_CPSTable; } + const char * const*seqCOLTable() { return _seq_COLTable; } + const char * const*seqTextsTable() { return _seq_textsTable; } + + const uint8 * const*palTable1() { return &_specialPalettes[0]; } + const uint8 * const*palTable2() { return &_specialPalettes[29]; } + +protected: + virtual int go(); + virtual int init(); + +public: + // sequences + // -> misc + bool seq_skipSequence() const; +protected: + // -> demo + void seq_demo(); + + // -> intro + void seq_intro(); + void seq_introLogos(); + void seq_introStory(); + void seq_introMalcolmTree(); + void seq_introKallakWriting(); + void seq_introKallakMalcolm(); + + // -> ingame animations + void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly); + void seq_brandonHealing(); + void seq_brandonHealing2(); + void seq_poisonDeathNow(int now); + void seq_poisonDeathNowAnim(); + void seq_playFluteAnimation(); + void seq_winterScroll1(); + void seq_winterScroll2(); + void seq_makeBrandonInv(); + void seq_makeBrandonNormal(); + void seq_makeBrandonNormal2(); + void seq_makeBrandonWisp(); + void seq_dispelMagicAnimation(); + void seq_fillFlaskWithWater(int item, int type); + void seq_playDrinkPotionAnim(int item, int unk2, int flags); + void seq_brandonToStone(); + + // -> end fight + int seq_playEnd(); + void seq_playEnding(); + + int handleMalcolmFlag(); + int handleBeadState(); + void initBeadState(int x, int y, int x2, int y2, int unk1, BeadState *ptr); + int processBead(int x, int y, int &x2, int &y2, BeadState *ptr); + + // -> credits + void seq_playCredits(); + +public: + // delay + void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); + void delay(uint32 millis, bool update = false, bool isMainLoop = false); + void delayWithTicks(int ticks); + void waitForEvent(); + + // TODO + void registerDefaultSettings(); + void readSettings(); + void writeSettings(); + + void snd_playSoundEffect(int track, int volume=0xFF); + void snd_playWanderScoreViaMap(int command, int restart); + virtual void snd_playVoiceFile(int id); + void snd_voiceWaitForFinish(bool ingame = true); + uint32 snd_getVoicePlayTime(); + +protected: + int32 _speechPlayTime; + + void saveGame(const char *fileName, const char *saveName); + void loadGame(const char *fileName); + +protected: + // input + void processInput(); + int processInputHelper(int xpos, int ypos); + int clickEventHandler(int xpos, int ypos); + void clickEventHandler2(); + void updateMousePointer(bool forceUpdate = false); + bool hasClickedOnExit(int xpos, int ypos); + + bool _skipFlag; + bool skipFlag() const { return _skipFlag; } + void resetSkipFlag(bool removeEvent = true) { _skipFlag = false; } + + // scene + // -> init + void loadSceneMsc(); + void startSceneScript(int brandonAlive); + void setupSceneItems(); + void initSceneData(int facing, int unk1, int brandonAlive); + void initSceneObjectList(int brandonAlive); + void initSceneScreen(int brandonAlive); + void setupSceneResource(int sceneId); + + // -> process + void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); + int handleSceneChange(int xpos, int ypos, int unk1, int frameReset); + int processSceneChange(int *table, int unk1, int frameReset); + int changeScene(int facing); + + // -> modification + void transcendScenes(int roomIndex, int roomName); + void setSceneFile(int roomIndex, int roomName); + + // -> pathfinder + int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); + bool lineIsPassable(int x, int y); + + // -> item handling + // --> misc + void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y); + + // --> drop handling + void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item); + int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2); + void dropItem(int unk1, int item, int x, int y, int unk2); + + // --> dropped item handling + int countItemsInScene(uint16 sceneId); + void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex); + byte findFreeItemInScene(int scene); + byte findItemAtPos(int x, int y); + + // --> drop area handling + void addToNoDropRects(int x, int y, int w, int h); + void clearNoDropRects(); + int isDropable(int x, int y); + int checkNoDropRects(int x, int y); + + // --> player items handling + void updatePlayerItemsForScene(); + + // --> item GFX handling + void backUpItemRect0(int xpos, int ypos); + void restoreItemRect0(int xpos, int ypos); + void backUpItemRect1(int xpos, int ypos); + void restoreItemRect1(int xpos, int ypos); + + // items + // -> misc + void placeItemInGenericMapScene(int item, int index); + + // -> mouse item + void setHandItem(uint16 item); + void removeHandItem(); + void setMouseItem(uint16 item); + + // -> graphics effects + void wipeDownMouseItem(int xpos, int ypos); + void itemSpecialFX(int x, int y, int item); + void itemSpecialFX1(int x, int y, int item); + void itemSpecialFX2(int x, int y, int item); + void magicOutMouseItem(int animIndex, int itemPos); + void magicInMouseItem(int animIndex, int item, int itemPos); + void specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops); + void processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops); + + // character + // -> movement + void moveCharacterToPos(int character, int facing, int xpos, int ypos); + void setCharacterPositionWithUpdate(int character); + int setCharacterPosition(int character, int *facingTable); + void setCharacterPositionHelper(int character, int *facingTable); + void setCharactersPositions(int character); + + // -> brandon + void setBrandonPoisonFlags(int reset); + void resetBrandonPoisonFlags(); + + // chat + // -> process + void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration); + void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum); + + // -> initialization + int initCharacterChat(int8 charNum); + void backupChatPartnerAnimFrame(int8 charNum); + void restoreChatPartnerAnimFrame(int8 charNum); + int8 getChatPartnerNum(); + + // -> deinitialization + void endCharacterChat(int8 charNum, int16 arg_4); + + // graphics + // -> misc + int findDuplicateItemShape(int shape); + void updateKyragemFading(); + + // -> interface + void loadMainScreen(int page = 3); + void redrawInventory(int page); +public: + void drawSentenceCommand(const char *sentence, int unk1); + void updateSentenceCommand(const char *str1, const char *str2, int unk1); + void updateTextFade(); + +protected: + // -> amulet + void drawJewelPress(int jewel, int drawSpecial); + void drawJewelsFadeOutStart(); + void drawJewelsFadeOutEnd(int jewel); + + // -> shape handling + void setupShapes123(const Shape *shapeTable, int endShape, int flags); + void freeShapes123(); + + // misc (TODO) + void startup(); + void mainLoop(); + + int checkForNPCScriptRun(int xpos, int ypos); + void runNpcScript(int func); + + void loadMouseShapes(); + void loadCharacterShapes(); + void loadSpecialEffectShapes(); + void loadItems(); + void loadButtonShapes(); + void initMainButtonList(); + void setCharactersInDefaultScene(); + void setupPanPages(); + void freePanPages(); + void closeFinalWsa(); + + //void setTimer19(); + void setupTimers(); + void timerUpdateHeadAnims(int timerNum); + void timerSetFlags1(int timerNum); + void timerSetFlags2(int timerNum); + void timerSetFlags3(int timerNum); + void timerCheckAnimFlag1(int timerNum); + void timerCheckAnimFlag2(int timerNum); + void checkAmuletAnimFlags(); + void timerRedrawAmulet(int timerNum); + void timerFadeText(int timerNum); + void updateAnimFlag1(int timerNum); + void updateAnimFlag2(int timerNum); + void drawAmulet(); + void setTextFadeTimerCountdown(int16 countdown); + void setWalkspeed(uint8 newSpeed); + + int buttonInventoryCallback(Button *caller); + int buttonAmuletCallback(Button *caller); + + bool _skipIntroFlag; + bool _abortIntroFlag; + bool _menuDirectlyToLoad; + bool _abortWalkFlag; + bool _abortWalkFlag2; + bool _mousePressFlag; + uint8 *_itemBkgBackUp[2]; + uint8 *_shapes[373]; + int8 _itemInHand; + bool _handleInput; + bool _changedScene; + int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3; + int _beadStateVar; + int _unkAmuletVar; + + int _malcolmFlag; + int _endSequenceSkipFlag; + int _endSequenceNeedLoading; + int _unkEndSeqVar2; + uint8 *_endSequenceBackUpRect; + int _unkEndSeqVar4; + int _unkEndSeqVar5; + int _lastDisplayedPanPage; + uint8 *_panPagesTable[20]; + Movie *_finalA, *_finalB, *_finalC; + + Movie *_movieObjects[10]; + + uint16 _entranceMouseCursorTracks[8]; + uint16 _walkBlockNorth; + uint16 _walkBlockEast; + uint16 _walkBlockSouth; + uint16 _walkBlockWest; + + int32 _scaleMode; + int16 _scaleTable[145]; + + Rect _noDropRects[11]; + + int8 _birthstoneGemTable[4]; + int8 _idolGemsTable[3]; + + int8 _marbleVaseItem; + int8 _foyerItemTable[3]; + + int8 _cauldronState; + int8 _crystalState[2]; + + uint16 _brandonStatusBit; + uint8 _brandonStatusBit0x02Flag; + uint8 _brandonStatusBit0x20Flag; + uint8 _brandonPoisonFlagsGFX[256]; + int16 _brandonInvFlag; + uint8 _poisonDeathCounter; + int _brandonPosX; + int _brandonPosY; + + uint16 _currentChatPartnerBackupFrame; + uint16 _currentCharAnimFrame; + + int8 *_sceneAnimTable[50]; + + Item _itemTable[145]; + int _lastProcessedItem; + int _lastProcessedItemHeight; + + int16 *_exitListPtr; + int16 _exitList[11]; + SceneExits _sceneExits; + uint16 _currentRoom; + int _scenePhasingFlag; + + int _sceneChangeState; + int _loopFlag2; + + int _pathfinderFlag; + int _pathfinderFlag2; + int _lastFindWayRet; + int *_movFacingTable; + + int8 _talkingCharNum; + int8 _charSayUnk2; + int8 _charSayUnk3; + int8 _currHeadShape; + uint8 _currSentenceColor[3]; + int8 _startSentencePalIndex; + bool _fadeText; + + uint8 _configTextspeed; + + Animator_LoK *_animator; + SeqPlayer *_seq; + Sprites *_sprites; + Screen_LoK *_screen; + + EMCState _scriptMain; + + EMCState _npcScript; + EMCData _npcScriptData; + + EMCState _scriptClick; + EMCData _scriptClickData; + + Character *_characterList; + Character *_currentCharacter; + + Button *_buttonList; + GUI_LoK *_gui; + + struct KyragemState { + uint16 nextOperation; + uint16 rOffset; + uint16 gOffset; + uint16 bOffset; + uint32 timerCount; + } _kyragemFadingState; + + static const int8 _dosTrackMap[]; + static const int _dosTrackMapSize; + + // TODO: get rid of all variables having pointers to the static resources if possible + // i.e. let them directly use the _staticres functions + void initStaticResource(); + + const uint8 *_seq_Forest; + const uint8 *_seq_KallakWriting; + const uint8 *_seq_KyrandiaLogo; + const uint8 *_seq_KallakMalcolm; + const uint8 *_seq_MalcolmTree; + const uint8 *_seq_WestwoodLogo; + const uint8 *_seq_Demo1; + const uint8 *_seq_Demo2; + const uint8 *_seq_Demo3; + const uint8 *_seq_Demo4; + const uint8 *_seq_Reunion; + + const char * const*_seq_WSATable; + const char * const*_seq_CPSTable; + const char * const*_seq_COLTable; + const char * const*_seq_textsTable; + + int _seq_WSATable_Size; + int _seq_CPSTable_Size; + int _seq_COLTable_Size; + int _seq_textsTable_Size; + + const char * const*_itemList; + const char * const*_takenList; + const char * const*_placedList; + const char * const*_droppedList; + const char * const*_noDropList; + const char * const*_putDownFirst; + const char * const*_waitForAmulet; + const char * const*_blackJewel; + const char * const*_poisonGone; + const char * const*_healingTip; + const char * const*_thePoison; + const char * const*_fluteString; + const char * const*_wispJewelStrings; + const char * const*_magicJewelString; + const char * const*_flaskFull; + const char * const*_fullFlask; + const char * const*_veryClever; + const char * const*_homeString; + const char * const*_newGameString; + + int _itemList_Size; + int _takenList_Size; + int _placedList_Size; + int _droppedList_Size; + int _noDropList_Size; + int _putDownFirst_Size; + int _waitForAmulet_Size; + int _blackJewel_Size; + int _poisonGone_Size; + int _healingTip_Size; + int _thePoison_Size; + int _fluteString_Size; + int _wispJewelStrings_Size; + int _magicJewelString_Size; + int _flaskFull_Size; + int _fullFlask_Size; + int _veryClever_Size; + int _homeString_Size; + int _newGameString_Size; + + const char * const*_characterImageTable; + int _characterImageTableSize; + + const char * const*_guiStrings; + int _guiStringsSize; + + const char * const*_configStrings; + int _configStringsSize; + + Shape *_defaultShapeTable; + int _defaultShapeTableSize; + + const Shape *_healingShapeTable; + int _healingShapeTableSize; + const Shape *_healingShape2Table; + int _healingShape2TableSize; + + const Shape *_posionDeathShapeTable; + int _posionDeathShapeTableSize; + + const Shape *_fluteAnimShapeTable; + int _fluteAnimShapeTableSize; + + const Shape *_winterScrollTable; + int _winterScrollTableSize; + const Shape *_winterScroll1Table; + int _winterScroll1TableSize; + const Shape *_winterScroll2Table; + int _winterScroll2TableSize; + + const Shape *_drinkAnimationTable; + int _drinkAnimationTableSize; + + const Shape *_brandonToWispTable; + int _brandonToWispTableSize; + + const Shape *_magicAnimationTable; + int _magicAnimationTableSize; + + const Shape *_brandonStoneTable; + int _brandonStoneTableSize; + + Room *_roomTable; + int _roomTableSize; + const char * const*_roomFilenameTable; + int _roomFilenameTableSize; + + const uint8 *_amuleteAnim; + + const uint8 * const*_specialPalettes; + + const char *const *_soundFiles; + int _soundFilesSize; + const char *const *_soundFilesIntro; + int _soundFilesIntroSize; + const int32 *_cdaTrackTable; + int _cdaTrackTableSize; + const AudioDataStruct * _soundData; + + // positions of the inventory + static const uint16 _itemPosX[]; + static const uint8 _itemPosY[]; + + void setupButtonData(); + Button *_buttonData; + Button **_buttonDataListPtr; + + static const uint8 _magicMouseItemStartFrame[]; + static const uint8 _magicMouseItemEndFrame[]; + static const uint8 _magicMouseItemStartFrame2[]; + static const uint8 _magicMouseItemEndFrame2[]; + + static const uint16 _amuletX[]; + static const uint16 _amuletY[]; + static const uint16 _amuletX2[]; + static const uint16 _amuletY2[]; +protected: + void setupOpcodeTable(); + + // Opcodes + int o1_magicInMouseItem(EMCState *script); + int o1_characterSays(EMCState *script); + int o1_delay(EMCState *script); + int o1_drawSceneAnimShape(EMCState *script); + int o1_runNPCScript(EMCState *script); + int o1_setSpecialExitList(EMCState *script); + int o1_walkPlayerToPoint(EMCState *script); + int o1_dropItemInScene(EMCState *script); + int o1_drawAnimShapeIntoScene(EMCState *script); + int o1_savePageToDisk(EMCState *script); + int o1_sceneAnimOn(EMCState *script); + int o1_sceneAnimOff(EMCState *script); + int o1_getElapsedSeconds(EMCState *script); + int o1_mouseIsPointer(EMCState *script); + int o1_runSceneAnimUntilDone(EMCState *script); + int o1_fadeSpecialPalette(EMCState *script); + int o1_phaseInSameScene(EMCState *script); + int o1_setScenePhasingFlag(EMCState *script); + int o1_resetScenePhasingFlag(EMCState *script); + int o1_queryScenePhasingFlag(EMCState *script); + int o1_sceneToDirection(EMCState *script); + int o1_setBirthstoneGem(EMCState *script); + int o1_placeItemInGenericMapScene(EMCState *script); + int o1_setBrandonStatusBit(EMCState *script); + int o1_delaySecs(EMCState *script); + int o1_getCharacterScene(EMCState *script); + int o1_runNPCSubscript(EMCState *script); + int o1_magicOutMouseItem(EMCState *script); + int o1_internalAnimOn(EMCState *script); + int o1_forceBrandonToNormal(EMCState *script); + int o1_poisonDeathNow(EMCState *script); + int o1_setScaleMode(EMCState *script); + int o1_openWSAFile(EMCState *script); + int o1_closeWSAFile(EMCState *script); + int o1_runWSAFromBeginningToEnd(EMCState *script); + int o1_displayWSAFrame(EMCState *script); + int o1_enterNewScene(EMCState *script); + int o1_setSpecialEnterXAndY(EMCState *script); + int o1_runWSAFrames(EMCState *script); + int o1_popBrandonIntoScene(EMCState *script); + int o1_restoreAllObjectBackgrounds(EMCState *script); + int o1_setCustomPaletteRange(EMCState *script); + int o1_loadPageFromDisk(EMCState *script); + int o1_customPrintTalkString(EMCState *script); + int o1_restoreCustomPrintBackground(EMCState *script); + int o1_getCharacterX(EMCState *script); + int o1_getCharacterY(EMCState *script); + int o1_setCharacterFacing(EMCState *script); + int o1_copyWSARegion(EMCState *script); + int o1_printText(EMCState *script); + int o1_loadSoundFile(EMCState *script); + int o1_displayWSAFrameOnHidPage(EMCState *script); + int o1_displayWSASequentialFrames(EMCState *script); + int o1_refreshCharacter(EMCState *script); + int o1_internalAnimOff(EMCState *script); + int o1_changeCharactersXAndY(EMCState *script); + int o1_clearSceneAnimatorBeacon(EMCState *script); + int o1_querySceneAnimatorBeacon(EMCState *script); + int o1_refreshSceneAnimator(EMCState *script); + int o1_placeItemInOffScene(EMCState *script); + int o1_wipeDownMouseItem(EMCState *script); + int o1_placeCharacterInOtherScene(EMCState *script); + int o1_getKey(EMCState *script); + int o1_specificItemInInventory(EMCState *script); + int o1_popMobileNPCIntoScene(EMCState *script); + int o1_mobileCharacterInScene(EMCState *script); + int o1_hideMobileCharacter(EMCState *script); + int o1_unhideMobileCharacter(EMCState *script); + int o1_setCharacterLocation(EMCState *script); + int o1_walkCharacterToPoint(EMCState *script); + int o1_specialEventDisplayBrynnsNote(EMCState *script); + int o1_specialEventRemoveBrynnsNote(EMCState *script); + int o1_setLogicPage(EMCState *script); + int o1_fatPrint(EMCState *script); + int o1_preserveAllObjectBackgrounds(EMCState *script); + int o1_updateSceneAnimations(EMCState *script); + int o1_sceneAnimationActive(EMCState *script); + int o1_setCharacterMovementDelay(EMCState *script); + int o1_getCharacterFacing(EMCState *script); + int o1_bkgdScrollSceneAndMasksRight(EMCState *script); + int o1_dispelMagicAnimation(EMCState *script); + int o1_findBrightestFireberry(EMCState *script); + int o1_setFireberryGlowPalette(EMCState *script); + int o1_setDeathHandlerFlag(EMCState *script); + int o1_drinkPotionAnimation(EMCState *script); + int o1_makeAmuletAppear(EMCState *script); + int o1_drawItemShapeIntoScene(EMCState *script); + int o1_setCharacterCurrentFrame(EMCState *script); + int o1_waitForConfirmationMouseClick(EMCState *script); + int o1_pageFlip(EMCState *script); + int o1_setSceneFile(EMCState *script); + int o1_getItemInMarbleVase(EMCState *script); + int o1_setItemInMarbleVase(EMCState *script); + int o1_addItemToInventory(EMCState *script); + int o1_intPrint(EMCState *script); + int o1_shakeScreen(EMCState *script); + int o1_createAmuletJewel(EMCState *script); + int o1_setSceneAnimCurrXY(EMCState *script); + int o1_poisonBrandonAndRemaps(EMCState *script); + int o1_fillFlaskWithWater(EMCState *script); + int o1_getCharacterMovementDelay(EMCState *script); + int o1_getBirthstoneGem(EMCState *script); + int o1_queryBrandonStatusBit(EMCState *script); + int o1_playFluteAnimation(EMCState *script); + int o1_playWinterScrollSequence(EMCState *script); + int o1_getIdolGem(EMCState *script); + int o1_setIdolGem(EMCState *script); + int o1_totalItemsInScene(EMCState *script); + int o1_restoreBrandonsMovementDelay(EMCState *script); + int o1_setEntranceMouseCursorTrack(EMCState *script); + int o1_itemAppearsOnGround(EMCState *script); + int o1_setNoDrawShapesFlag(EMCState *script); + int o1_fadeEntirePalette(EMCState *script); + int o1_itemOnGroundHere(EMCState *script); + int o1_queryCauldronState(EMCState *script); + int o1_setCauldronState(EMCState *script); + int o1_queryCrystalState(EMCState *script); + int o1_setCrystalState(EMCState *script); + int o1_setPaletteRange(EMCState *script); + int o1_shrinkBrandonDown(EMCState *script); + int o1_growBrandonUp(EMCState *script); + int o1_setBrandonScaleXAndY(EMCState *script); + int o1_resetScaleMode(EMCState *script); + int o1_getScaleDepthTableValue(EMCState *script); + int o1_setScaleDepthTableValue(EMCState *script); + int o1_message(EMCState *script); + int o1_checkClickOnNPC(EMCState *script); + int o1_getFoyerItem(EMCState *script); + int o1_setFoyerItem(EMCState *script); + int o1_setNoItemDropRegion(EMCState *script); + int o1_walkMalcolmOn(EMCState *script); + int o1_passiveProtection(EMCState *script); + int o1_setPlayingLoop(EMCState *script); + int o1_brandonToStoneSequence(EMCState *script); + int o1_brandonHealingSequence(EMCState *script); + int o1_protectCommandLine(EMCState *script); + int o1_pauseMusicSeconds(EMCState *script); + int o1_resetMaskRegion(EMCState *script); + int o1_setPaletteChangeFlag(EMCState *script); + int o1_vocUnload(EMCState *script); + int o1_vocLoad(EMCState *script); + int o1_dummy(EMCState *script); +}; + +} // end of namespace Kyra + +#endif + diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 61546fc2e7..8a49b8e155 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -23,7 +23,7 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_mr.h" #include "kyra/screen_mr.h" #include "kyra/wsamovie.h" @@ -50,13 +50,16 @@ const KyraEngine_v2::EngineDesc KyraEngine_MR::_mrEngineDesc = { 9, // Animation script specific - 9 + 9, + + // Item specific + 71 }; KyraEngine_MR::KyraEngine_MR(OSystem *system, const GameFlags &flags) : KyraEngine_v2(system, flags, _mrEngineDesc) { _soundDigital = 0; _musicSoundChannel = -1; - _menuAudioFile = "TITLE1.AUD"; + _menuAudioFile = "TITLE1"; _lastMusicCommand = -1; _itemBuffer1 = _itemBuffer2 = 0; _scoreFile = 0; @@ -71,13 +74,13 @@ KyraEngine_MR::KyraEngine_MR(OSystem *system, const GameFlags &flags) : KyraEngi _gfxBackUpRect = 0; _paletteOverlay = 0; _sceneList = 0; - memset(&_mainCharacter, 0, sizeof(_mainCharacter)); _mainCharacter.sceneId = 9; _mainCharacter.height = 0x4C; _mainCharacter.facing = 5; _mainCharacter.animFrame = 0x57; _mainCharacter.walkspeed = 5; - memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); + memset(_activeItemAnim, 0, sizeof(_activeItemAnim)); + _nextAnimItem = 0; _text = 0; _commandLineY = 189; _inventoryState = false; @@ -96,7 +99,7 @@ KyraEngine_MR::KyraEngine_MR(OSystem *system, const GameFlags &flags) : KyraEngi _unk5 = 0; _unkSceneScreenFlag1 = false; _noScriptEnter = true; - _itemInHand = _handItemSet = -1; + _itemInHand = _mouseState = -1; _unk3 = -1; _unk4 = 0; _loadingState = false; @@ -140,6 +143,12 @@ KyraEngine_MR::KyraEngine_MR(OSystem *system, const GameFlags &flags) : KyraEngi _menuDirectlyToLoad = false; _optionsFile = 0; _actorFile = 0; + _chatAltFlag = false; + _albumChatActive = false; + memset(&_album, 0, sizeof(_album)); + _configHelium = false; + _fadeOutMusicChannel = -1; + memset(_scaleTable, 0, sizeof(_scaleTable)); } KyraEngine_MR::~KyraEngine_MR() { @@ -152,6 +161,7 @@ KyraEngine_MR::~KyraEngine_MR() { delete[] _cCodeFile; delete[] _scenesFile; delete[] _itemFile; + delete[] _actorFile; delete[] _gamePlayBuffer; delete[] _interface; delete[] _interfaceCommandLine; @@ -165,7 +175,6 @@ KyraEngine_MR::~KyraEngine_MR() { delete[] _gfxBackUpRect; delete[] _paletteOverlay; - delete[] _sceneList; for (ShapeMap::iterator i = _gameShapes.begin(); i != _gameShapes.end(); ++i) { delete[] i->_value; @@ -187,6 +196,10 @@ KyraEngine_MR::~KyraEngine_MR() { delete[] _mainButtonData; delete _gui; delete[] _optionsFile; + + delete _album.wsa; + delete _album.leftPage.wsa; + delete _album.rightPage.wsa; } int KyraEngine_MR::init() { @@ -194,7 +207,8 @@ int KyraEngine_MR::init() { assert(_screen); _screen->setResolution(); - KyraEngine::init(); + KyraEngine_v1::init(); + initStaticResource(); _debugger = new Debugger_v2(this); assert(_debugger); @@ -203,7 +217,7 @@ int KyraEngine_MR::init() { assert(_soundDigital); if (!_soundDigital->init()) error("_soundDigital->init() failed"); - KyraEngine::_text = _text = new TextDisplayer_MR(this, _screen); + KyraEngine_v1::_text = _text = new TextDisplayer_MR(this, _screen); assert(_text); _gui = new GUI_MR(this); assert(_gui); @@ -272,6 +286,8 @@ int KyraEngine_MR::go() { delayUntil(nextRun); } + _eventList.clear(); + switch (_menu->handle(3)) { case 2: _menuDirectlyToLoad = true; @@ -312,7 +328,7 @@ int KyraEngine_MR::go() { } void KyraEngine_MR::initMainMenu() { - _menuAnim = new WSAMovieV2(this, _screen); + _menuAnim = new WSAMovie_v2(this, _screen); _menuAnim->open("REVENGE.WSA", 1, _screen->getPalette(0)); _menuAnim->setX(0); _menuAnim->setY(0); @@ -354,7 +370,10 @@ void KyraEngine_MR::playVQA(const char *name) { snprintf(filename, sizeof(filename), "%s%d.VQA", name, size); if (vqa.open(filename)) { - _soundDigital->stopAllSounds(); + for (int i = 0; i < 4; ++i) { + if (i != _musicSoundChannel) + _soundDigital->stopSound(i); + } _screen->hideMouse(); memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); @@ -386,14 +405,12 @@ void KyraEngine_MR::playMenuAudioFile() { if (_soundDigital->isPlaying(_musicSoundChannel)) return; - _musicSoundChannel = _soundDigital->playSound(_menuAudioFile, 0xFF, Audio::Mixer::kMusicSoundType); + _musicSoundChannel = _soundDigital->playSound(_menuAudioFile, 0xFF, Audio::Mixer::kMusicSoundType, 255, true); } void KyraEngine_MR::snd_playWanderScoreViaMap(int track, int force) { debugC(9, kDebugLevelMain, "KyraEngine_MR::snd_playWanderScoreViaMap(%d, %d)", track, force); - // XXX byte_3C87C compare - if (_musicSoundChannel != -1 && !_soundDigital->isPlaying(_musicSoundChannel)) force = 1; else if (_musicSoundChannel == -1) @@ -407,7 +424,9 @@ void KyraEngine_MR::snd_playWanderScoreViaMap(int track, int force) { if (_musicSoundChannel == -1) { assert(track < _soundListSize && track >= 0); - _musicSoundChannel = _soundDigital->playSound(_soundList[track], 0xFF, Audio::Mixer::kMusicSoundType); + char file[13]; + sprintf(file, "%s", _soundList[track]); + _musicSoundChannel = _soundDigital->playSound(file, 0xFF, Audio::Mixer::kMusicSoundType); } _lastMusicCommand = track; @@ -463,7 +482,8 @@ void KyraEngine_MR::snd_playSoundEffect(int item, int volume) { debugC(9, kDebugLevelMain, "KyraEngine_MR::snd_playSoundEffect(%d, %d)", item, volume); if (_sfxFileMap[item*2+0] != 0xFF) { char filename[16]; - snprintf(filename, 16, "%s.AUD", _sfxFileList[_sfxFileMap[item*2+0]]); + assert(_sfxFileMap[item*2+0] < _sfxFileListSize); + snprintf(filename, 16, "%s", _sfxFileList[_sfxFileMap[item*2+0]]); uint8 priority = _sfxFileMap[item*2+1]; _soundDigital->playSound(filename, priority, Audio::Mixer::kSFXSoundType, volume); @@ -478,7 +498,7 @@ void KyraEngine_MR::playVoice(int high, int low) { void KyraEngine_MR::snd_playVoiceFile(int file) { debugC(9, kDebugLevelMain, "KyraEngine_MR::snd_playVoiceFile(%d)", file); char filename[16]; - snprintf(filename, 16, "%u.AUD", (uint)file); + snprintf(filename, 16, "%.08u", (uint)file); _voiceSoundChannel = _soundDigital->playSound(filename, 0xFE, Audio::Mixer::kSpeechSoundType, 255); } @@ -531,14 +551,19 @@ void KyraEngine_MR::initMouseShapes() { assert(data); for (int i = 0; i <= 6; ++i) _gameShapes[i] = _screen->makeShapeCopy(data, i); - delete [] data; + delete[] data; } void KyraEngine_MR::startup() { debugC(9, kDebugLevelMain, "KyraEngine_MR::startup()"); - musicUpdate(0); - memset(_flagsTable, 0, sizeof(_flagsTable)); + _album.wsa = new WSAMovie_v2(this, _screen); + assert(_album.wsa); + _album.leftPage.wsa = new WSAMovie_v2(this, _screen); + assert(_album.leftPage.wsa); + _album.rightPage.wsa = new WSAMovie_v2(this, _screen); + assert(_album.rightPage.wsa); + musicUpdate(0); _gamePlayBuffer = new uint8[64000]; musicUpdate(0); @@ -552,7 +577,6 @@ void KyraEngine_MR::startup() { _stringBuffer = new char[500]; //XXX musicUpdate(0); - _costPalBuffer = new uint8[864]; //XXX allocAnimObjects(1, 16, 50); @@ -590,7 +614,7 @@ void KyraEngine_MR::startup() { for (int i = 0; i < 16; ++i) { _sceneAnims[i].flags = 0; - _sceneAnimMovie[i] = new WSAMovieV2(this, _screen); + _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen); assert(_sceneAnimMovie[i]); } @@ -647,7 +671,7 @@ void KyraEngine_MR::startup() { musicUpdate(0); runStartupScript(1, 0); _res->exists("MOODOMTR.WSA", true); - _invWsa = new WSAMovieV2(this, _screen); + _invWsa = new WSAMovie_v2(this, _screen); assert(_invWsa); _invWsa->open("MOODOMTR.WSA", 1, 0); _invWsaFrame = 6; @@ -672,7 +696,11 @@ void KyraEngine_MR::startup() { void KyraEngine_MR::loadCostPal() { debugC(9, kDebugLevelMain, "KyraEngine_MR::loadCostPal()"); - _costPalBuffer = _res->fileData("_COSTPAL.DAT", 0); + _res->exists("_COSTPAL.DAT", true); + uint32 size = 0; + _costPalBuffer = _res->fileData("_COSTPAL.DAT", &size); + assert(_costPalBuffer); + assert(size == 864); } void KyraEngine_MR::loadShadowShape() { @@ -725,7 +753,7 @@ void KyraEngine_MR::initItems() { memcpy(_itemBuffer1, itemsDat , 72); memcpy(_itemBuffer2, itemsDat+72, 144); - delete [] itemsDat; + delete[] itemsDat; _screen->_curPage = 0; } @@ -791,7 +819,7 @@ void KyraEngine_MR::loadCharacterShapes(int newShapes) { ShapeMap::iterator iter = _gameShapes.find(i); if (iter != _gameShapes.end()) { - delete iter->_value; + delete[] iter->_value; iter->_value = 0; } } @@ -978,7 +1006,7 @@ void KyraEngine_MR::runLoop() { _timer->update(); if (inputFlag == 198 || inputFlag == 199) { - _unk3 = _handItemSet; + _unk3 = _mouseState; Common::Point mouse = getMousePos(); handleInput(mouse.x, mouse.y); } @@ -1122,7 +1150,7 @@ void KyraEngine_MR::update() { updateMouse(); updateSpecialSceneScripts(); updateCommandLine(); - //XXX + updateItemAnimations(); musicUpdate(0); _screen->updateScreen(); @@ -1134,7 +1162,7 @@ void KyraEngine_MR::updateWithText() { musicUpdate(0); updateMouse(); - //XXX + updateItemAnimations(); updateSpecialSceneScripts(); updateCommandLine(); musicUpdate(0); @@ -1160,13 +1188,13 @@ void KyraEngine_MR::updateMouse() { if (mouse.y > 187) { bool setItemCursor = false; - if (_handItemSet == -6) { + if (_mouseState == -6) { if (mouse.x < 311) setItemCursor = true; - } else if (_handItemSet == -5) { + } else if (_mouseState == -5) { if (mouse.x < _sceneMinX || mouse.x > _sceneMaxX) setItemCursor = true; - } else if (_handItemSet == -4) { + } else if (_mouseState == -4) { if (mouse.x > 8) setItemCursor = true; } @@ -1183,8 +1211,8 @@ void KyraEngine_MR::updateMouse() { hideInventory(); } - if (hasItemCollision && _handItemSet < -1 && _itemInHand < 0) { - _handItemSet = -1; + if (hasItemCollision && _mouseState < -1 && _itemInHand < 0) { + _mouseState = -1; _itemInHand = -1; _screen->setMouseCursor(0, 0, _gameShapes[0]); } @@ -1261,29 +1289,16 @@ void KyraEngine_MR::updateMouse() { } } - if (type != 0 && type != _handItemSet && !hasItemCollision) { - _handItemSet = type; + if (type != 0 && type != _mouseState && !hasItemCollision) { + _mouseState = type; _screen->setMouseCursor(offsetX, offsetY, _gameShapes[shape]); - } else if (type == 0 && _handItemSet != _itemInHand && mouse.x > 8 && mouse.x < 311 && mouse.y < 171 && mouse.y > 8) { + } else if (type == 0 && _mouseState != _itemInHand && mouse.x > 8 && mouse.x < 311 && mouse.y < 171 && mouse.y > 8) { setItemMouseCursor(); - } else if (mouse.y > 187 && _handItemSet > -4 && type == 0 && !_inventoryState) { + } else if (mouse.y > 187 && _mouseState > -4 && type == 0 && !_inventoryState) { showInventory(); } } -void KyraEngine_MR::delay(uint32 millis, bool doUpdate, bool isMainLoop) { - debugC(9, kDebugLevelMain, "KyraEngine_MR::delay(%d, %d, %d)", millis, doUpdate, isMainLoop); - uint32 endTime = _system->getMillis() + millis; - while (endTime > _system->getMillis()) { - if (doUpdate) { - //XXX - update(); - } - - _system->delayMillis(10); - } -} - #pragma mark - void KyraEngine_MR::makeCharFacingMouse() { @@ -1501,13 +1516,14 @@ void KyraEngine_MR::resetSkipFlag(bool removeEvent) { void KyraEngine_MR::registerDefaultSettings() { debugC(9, kDebugLevelMain, "KyraEngine_MR::registerDefaultSettings()"); - KyraEngine::registerDefaultSettings(); + KyraEngine_v1::registerDefaultSettings(); // Most settings already have sensible defaults. This one, however, is // specific to the Kyra engine. ConfMan.registerDefault("walkspeed", 5); ConfMan.registerDefault("studio_audience", true); ConfMan.registerDefault("skip_support", true); + ConfMan.registerDefault("helium_mode", false); } void KyraEngine_MR::writeSettings() { @@ -1531,16 +1547,18 @@ void KyraEngine_MR::writeSettings() { ConfMan.setBool("studio_audience", _configStudio); ConfMan.setBool("skip_support", _configSkip); + ConfMan.setBool("helium_mode", _configHelium); - KyraEngine::writeSettings(); + KyraEngine_v1::writeSettings(); } void KyraEngine_MR::readSettings() { debugC(9, kDebugLevelMain, "KyraEngine_MR::readSettings()"); - KyraEngine::readSettings(); + KyraEngine_v1::readSettings(); _configStudio = ConfMan.getBool("studio_audience"); _configSkip = ConfMan.getBool("skip_support"); + _configHelium = ConfMan.getBool("helium_mode"); } } // end of namespace Kyra diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 3dba3ec8d9..5af138373c 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -23,8 +23,8 @@ * */ -#ifndef KYRA_KYRA_V3_H -#define KYRA_KYRA_V3_H +#ifndef KYRA_KYRA_MR_H +#define KYRA_KYRA_MR_H #include "kyra/kyra_v2.h" #include "kyra/screen_mr.h" @@ -39,7 +39,7 @@ namespace Kyra { class SoundDigital; class Screen_MR; class MainMenu; -class WSAMovieV2; +class WSAMovie_v2; class TextDisplayer_MR; struct Button; @@ -50,11 +50,17 @@ public: KyraEngine_MR(OSystem *system, const GameFlags &flags); ~KyraEngine_MR(); + //TODO: proper extended implementation of KyraEngine_v2::pauseEngineIntern. + // Idle animation time, item animations and album animations should be taken + // care of, but since those would just produce minor glitches it's not that + // important. + Screen *screen() { return _screen; } Screen_v2 *screen_v2() const { return _screen; } GUI_v2 *gui_v2() const { return _gui; } SoundDigital *soundDigital() { return _soundDigital; } int language() const { return _lang; } + bool heliumMode() const { return _configHelium; } int go(); @@ -66,11 +72,14 @@ private: // config bool _configStudio; bool _configSkip; + bool _configHelium; void registerDefaultSettings(); void writeSettings(); void readSettings(); + void initStaticResource(); + // -- Screen_MR *_screen; SoundDigital *_soundDigital; @@ -98,8 +107,6 @@ private: void updateWithText(); void updateMouse(); - void delay(uint32 millis, bool update = false, bool isMainLoop = false); - // sound specific private: void playMenuAudioFile(); @@ -108,8 +115,8 @@ private: int _fadeOutMusicChannel; const char *_menuAudioFile; - static const char *_soundList[]; - static const int _soundListSize; + const char *const *_soundList; + int _soundListSize; void snd_playWanderScoreViaMap(int track, int force); void stopMusicTrack(); @@ -119,10 +126,10 @@ private: void snd_playSoundEffect(int item, int volume); - static const uint8 _sfxFileMap[]; - static const int _sfxFileMapSize; - static const char *_sfxFileList[]; - static const int _sfxFileListSize; + const uint8 *_sfxFileMap; + int _sfxFileMapSize; + const char *const *_sfxFileList; + int _sfxFileListSize; int _voiceSoundChannel; @@ -157,7 +164,7 @@ private: void initMainMenu(); void uninitMainMenu(); - WSAMovieV2 *_menuAnim; + WSAMovie_v2 *_menuAnim; // timer void setupTimers(); @@ -177,7 +184,8 @@ private: private: // main menu - static const char *_mainMenuStrings[]; + const char *const *_mainMenuStrings; + int _mainMenuStringsSize; // animator uint8 *_gamePlayBuffer; @@ -194,6 +202,7 @@ private: void refreshAnimObjects(int force); bool _loadingState; + void updateItemAnimations(); void updateCharacterAnim(int charId); void updateSceneAnim(int anim, int newFrame); @@ -209,6 +218,10 @@ private: bool _nextIdleType; void showIdleAnim(); + const ItemAnimData_v2 *_itemAnimData; + ActiveItemAnim _activeItemAnim[10]; + int _nextAnimItem; + // interface uint8 *_interface; uint8 *_interfaceCommandLine; @@ -247,7 +260,7 @@ private: void clearInventorySlot(int slot, int page); void drawInventorySlot(int page, int item, int slot); - WSAMovieV2 *_invWsa; + WSAMovie_v2 *_invWsa; int _invWsaFrame; // localization @@ -282,12 +295,12 @@ private: bool isDropable(int x, int y); - static const uint8 _itemMagicTable[]; + const uint8 *_itemMagicTable; bool itemListMagic(int handItem, int itemSlot); bool itemInventoryMagic(int handItem, int invSlot); - static const uint8 _itemStringMap[]; - static const uint _itemStringMapSize; + const uint8 *_itemStringMap; + int _itemStringMapSize; static const uint8 _itemStringPickUp[]; static const uint8 _itemStringDrop[]; static const uint8 _itemStringInv[]; @@ -415,6 +428,11 @@ private: void goodConscienceChat(const char *str, int vocHigh, int vocLow); void goodConscienceChatWaitToFinish(); + bool _albumChatActive; + void albumChat(const char *str, int vocHigh, int vocLow); + void albumChatInit(const char *str, int object, int vocHigh, int vocLow); + void albumChatWaitToFinish(); + void malcolmSceneStartupChat(); byte _newSceneDlgState[40]; @@ -503,14 +521,64 @@ private: int _score; int _scoreMax; - static const int8 _scoreTable[]; - static const int _scoreTableSize; + const uint8 *_scoreTable; + int _scoreTableSize; + int8 _scoreFlagTable[26]; bool updateScore(int scoreId, int strId); void scoreIncrease(int count, const char *str); void eelScript(); + // Album + struct Album { + uint8 *backUpPage; + uint8 *file; + WSAMovie_v2 *wsa; + uint8 *backUpRect; + + struct PageMovie { + WSAMovie_v2 *wsa; + int curFrame; + int maxFrame; + uint32 timer; + }; + + PageMovie leftPage, rightPage; + + int curPage, nextPage; + bool running; + bool isPage14; + } _album; + + static const int8 _albumWSAX[]; + static const int8 _albumWSAY[]; + + void showAlbum(); + + void loadAlbumPage(); + void loadAlbumPageWSA(); + + void printAlbumPageText(); + void printAlbumText(int page, const char *str, int x, int y, uint8 c0); + + void processAlbum(); + + void albumNewPage(); + void albumUpdateAnims(); + void albumAnim1(); + void albumAnim2(); + + void albumBackUpRect(); + void albumRestoreRect(); + void albumUpdateRect(); + + void albumSwitchPages(int oldPage, int newPage, int srcPage); + + int albumNextPage(Button *caller); + int albumPrevPage(Button *caller); + int albumClose(Button *caller); + // save/load void saveGame(const char *fileName, const char *saveName); void loadGame(const char *fileName); @@ -527,6 +595,7 @@ private: int o3_setCharacterAnimFrameFromFacing(EMCState *script); int o3_showBadConscience(EMCState *script); int o3_hideBadConscience(EMCState *script); + int o3_showAlbum(EMCState *script); int o3_setInventorySlot(EMCState *script); int o3_getInventorySlot(EMCState *script); int o3_addItemToInventory(EMCState *script); @@ -548,6 +617,7 @@ private: int o3_drawSceneShapeOnPage(EMCState *script); int o3_checkInRect(EMCState *script); int o3_updateConversations(EMCState *script); + int o3_removeItemSlot(EMCState *script); int o3_setSceneDim(EMCState *script); int o3_setSceneAnimPosAndFrame(EMCState *script); int o3_removeItemInstances(EMCState *script); @@ -560,7 +630,7 @@ private: int o3_playSoundEffect(EMCState *script); int o3_getScore(EMCState *script); int o3_daggerWarning(EMCState *script); - int o3_blockOutRegion(EMCState *script); + int o3_blockOutWalkableRegion(EMCState *script); int o3_showSceneStringsMessage(EMCState *script); int o3_showGoodConscience(EMCState *script); int o3_goodConscienceChat(EMCState *script); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index e9bb25fe5f..1cc1d728bf 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -23,1024 +23,386 @@ * */ -#include "kyra/kyra_v1.h" - -#include "common/file.h" -#include "common/events.h" -#include "common/system.h" -#include "common/savefile.h" +#include "common/config-manager.h" -#include "gui/message.h" +#include "sound/mididrv.h" +#include "sound/mixer.h" +#include "kyra/kyra_v1.h" +#include "kyra/sound.h" #include "kyra/resource.h" #include "kyra/screen.h" -#include "kyra/script.h" -#include "kyra/seqplayer.h" -#include "kyra/sound.h" -#include "kyra/sprites.h" -#include "kyra/wsamovie.h" -#include "kyra/animator_v1.h" #include "kyra/text.h" -#include "kyra/debugger.h" #include "kyra/timer.h" +#include "kyra/script.h" +#include "kyra/debugger.h" namespace Kyra { KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags) - : KyraEngine(system, flags) { - _skipFlag = false; - - _seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm = - _seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 = - _seq_Demo4 = 0; - - _seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0; - _seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0; - - _roomFilenameTable = _characterImageTable = 0; - _roomFilenameTableSize = _characterImageTableSize = 0; - _itemList = _takenList = _placedList = _droppedList = _noDropList = 0; - _itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0; - _putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0; - _putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0; - _thePoison = _fluteString = _wispJewelStrings = _magicJewelString = _flaskFull = _fullFlask = 0; - _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0; - _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0; - - _defaultShapeTable = 0; - _healingShapeTable = _healingShape2Table = 0; - _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0; - _posionDeathShapeTable = _fluteAnimShapeTable = 0; - _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0; - _winterScrollTable = _winterScroll1Table = _winterScroll2Table = 0; - _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0; - _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0; - _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0; - memset(&_specialPalettes, 0, sizeof(_specialPalettes)); + : Engine(system), _flags(flags) { + _res = 0; + _sound = 0; + _text = 0; + _staticres = 0; + _timer = 0; + _emc = 0; _debugger = 0; - _sprites = 0; - _animator = 0; - _seq = 0; - _characterList = 0; - _movFacingTable = 0; - _buttonData = 0; - _buttonDataListPtr = 0; - memset(_shapes, 0, sizeof(_shapes)); - memset(_movieObjects, 0, sizeof(_movieObjects)); - _finalA = _finalB = _finalC = 0; - _endSequenceBackUpRect = 0; - memset(_panPagesTable, 0, sizeof(_panPagesTable)); - memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); - _currHeadShape = 0; - - memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp)); -} - -KyraEngine_v1::~KyraEngine_v1() { - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) { - if (_movieObjects[i]) - _movieObjects[i]->close(); - delete _movieObjects[i]; - _movieObjects[i] = 0; - } - - closeFinalWsa(); - if (_emc) { - _emc->unload(&_npcScriptData); - _emc->unload(&_scriptClickData); - } - - Common::clearAllSpecialDebugLevels(); - - delete _screen; - delete _debugger; - delete _sprites; - delete _animator; - delete _seq; - - delete [] _characterList; - - delete [] _movFacingTable; - - delete [] _gui->_scrollUpButton.data0ShapePtr; - delete [] _gui->_scrollUpButton.data1ShapePtr; - delete [] _gui->_scrollUpButton.data2ShapePtr; - delete [] _gui->_scrollDownButton.data0ShapePtr; - delete [] _gui->_scrollDownButton.data1ShapePtr; - delete [] _gui->_scrollDownButton.data2ShapePtr; - - delete [] _buttonData; - delete [] _buttonDataListPtr; - - delete _gui; - - delete [] _itemBkgBackUp[0]; - delete [] _itemBkgBackUp[1]; - - for (int i = 0; i < ARRAYSIZE(_shapes); ++i) { - if (_shapes[i] != 0) { - delete [] _shapes[i]; - for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) { - if (_shapes[i2] == _shapes[i] && i2 != i) { - _shapes[i2] = 0; - } - } - _shapes[i] = 0; - } - } - - for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) - delete [] _sceneAnimTable[i]; -} - -int KyraEngine_v1::init() { - _screen = new Screen_v1(this, _system); - assert(_screen); - _screen->setResolution(); - - KyraEngine::init(); - - _sprites = new Sprites(this, _system); - assert(_sprites); - _seq = new SeqPlayer(this, _system); - assert(_seq); - _animator = new Animator_v1(this, _system); - assert(_animator); - _animator->init(5, 11, 12); - assert(*_animator); - _text = new TextDisplayer(this, screen()); - assert(_text); - _gui = new GUI_v1(this, _screen); - assert(_gui); - - initStaticResource(); - - _sound->setSoundList(&_soundData[kMusicIntro]); - - _trackMap = _dosTrackMap; - _trackMapSize = _dosTrackMapSize; - - if (!_sound->init()) - error("Couldn't init sound"); - _sound->loadSoundFile(0); + _gameSpeed = 60; + _tickLength = (uint8)(1000.0 / _gameSpeed); - setupButtonData(); + _quitFlag = false; - _paletteChanged = 1; - _currentCharacter = 0; - _characterList = new Character[11]; - assert(_characterList); - memset(_characterList, 0, sizeof(Character)*11); + _speechFile = ""; + _trackMap = 0; + _trackMapSize = 0; + _lastMusicCommand = -1; + _curSfxFile = _curMusicTheme = -1; - for (int i = 0; i < 11; ++i) - memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems)); + _gameToLoad = -1; - _characterList[0].sceneId = 5; - _characterList[0].height = 48; - _characterList[0].facing = 3; - _characterList[0].currentAnimFrame = 7; - - memset(&_npcScriptData, 0, sizeof(EMCData)); - memset(&_scriptClickData, 0, sizeof(EMCData)); - - memset(&_npcScript, 0, sizeof(EMCState)); - memset(&_scriptMain, 0, sizeof(EMCState)); - memset(&_scriptClick, 0, sizeof(EMCState)); - - _debugger = new Debugger_v1(this); - assert(_debugger); - memset(_shapes, 0, sizeof(_shapes)); - - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) - _movieObjects[i] = createWSAMovie(); + _mouseState = -1; + _deathHandler = -1; memset(_flagsTable, 0, sizeof(_flagsTable)); - _abortWalkFlag = false; - _abortWalkFlag2 = false; - _talkingCharNum = -1; - _charSayUnk3 = -1; - memset(_currSentenceColor, 0, 3); - _startSentencePalIndex = -1; - _fadeText = false; - - _cauldronState = 0; - _crystalState[0] = _crystalState[1] = -1; - - _brandonStatusBit = 0; - _brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10; - _brandonPosX = _brandonPosY = -1; - _deathHandler = 0xFF; - _poisonDeathCounter = 0; - - memset(_itemTable, 0, sizeof(_itemTable)); - memset(_exitList, 0xFFFF, sizeof(_exitList)); - _exitListPtr = 0; - _pathfinderFlag = _pathfinderFlag2 = 0; - _lastFindWayRet = 0; - _sceneChangeState = _loopFlag2 = 0; - - _movFacingTable = new int[150]; - assert(_movFacingTable); - _movFacingTable[0] = 8; - - _skipFlag = false; - - _marbleVaseItem = -1; - memset(_foyerItemTable, -1, sizeof(_foyerItemTable)); - _mouseState = _itemInHand = -1; - _handleInput = false; - - _currentRoom = 0xFFFF; - _scenePhasingFlag = 0; - _lastProcessedItem = 0; - _lastProcessedItemHeight = 16; - - _unkScreenVar1 = 1; - _unkScreenVar2 = 0; - _unkScreenVar3 = 0; - _unkAmuletVar = 0; - - _endSequenceNeedLoading = 1; - _malcolmFlag = 0; - _beadStateVar = 0; - _endSequenceSkipFlag = 0; - _unkEndSeqVar2 = 0; - _endSequenceBackUpRect = 0; - _unkEndSeqVar4 = 0; - _unkEndSeqVar5 = 0; - _lastDisplayedPanPage = 0; - memset(_panPagesTable, 0, sizeof(_panPagesTable)); - _finalA = _finalB = _finalC = 0; - memset(&_kyragemFadingState, 0, sizeof(_kyragemFadingState)); - _kyragemFadingState.gOffset = 0x13; - _kyragemFadingState.bOffset = 0x13; - - _mousePressFlag = false; - - _menuDirectlyToLoad = false; - - _lastMusicCommand = 0; - - return 0; + // sets up all engine specific debug levels + Common::addSpecialDebugLevel(kDebugLevelScriptFuncs, "ScriptFuncs", "Script function debug level"); + Common::addSpecialDebugLevel(kDebugLevelScript, "Script", "Script interpreter debug level"); + Common::addSpecialDebugLevel(kDebugLevelSprites, "Sprites", "Sprite debug level"); + Common::addSpecialDebugLevel(kDebugLevelScreen, "Screen", "Screen debug level"); + Common::addSpecialDebugLevel(kDebugLevelSound, "Sound", "Sound debug level"); + Common::addSpecialDebugLevel(kDebugLevelAnimator, "Animator", "Animator debug level"); + Common::addSpecialDebugLevel(kDebugLevelMain, "Main", "Generic debug level"); + Common::addSpecialDebugLevel(kDebugLevelGUI, "GUI", "GUI debug level"); + Common::addSpecialDebugLevel(kDebugLevelSequence, "Sequence", "Sequence debug level"); + Common::addSpecialDebugLevel(kDebugLevelMovie, "Movie", "Movie debug level"); + Common::addSpecialDebugLevel(kDebugLevelTimer, "Timer", "Timer debug level"); + + system->getEventManager()->registerRandomSource(_rnd, "kyra"); } -int KyraEngine_v1::go() { - if (_res->getFileSize("6.FNT")) - _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); - _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); - _screen->setScreenDim(0); - - _abortIntroFlag = false; - - if (_flags.isDemo) { - seq_demo(); - } else { - setGameFlag(0xF3); - setGameFlag(0xFD); - if (_gameToLoad == -1) { - setGameFlag(0xEF); - seq_intro(); - if (_quitFlag) - return 0; - if (_skipIntroFlag && _abortIntroFlag) - resetGameFlag(0xEF); - } - startup(); - resetGameFlag(0xEF); - mainLoop(); - } - return 0; +::GUI::Debugger *KyraEngine_v1::getDebugger() { + return _debugger; } +void KyraEngine_v1::pauseEngineIntern(bool pause) { + Engine::pauseEngineIntern(pause); + _timer->pause(pause); +} -void KyraEngine_v1::startup() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::startup()"); - static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 }; - _screen->setTextColorMap(colorMap); - _sound->setSoundList(&_soundData[kMusicIngame]); - _sound->loadSoundFile(0); -// _screen->setFont(Screen::FID_6_FNT); - _screen->setAnimBlockPtr(3750); - memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); - loadMouseShapes(); - _currentCharacter = &_characterList[0]; - for (int i = 1; i < 5; ++i) - _animator->setCharacterDefaultFrame(i); - for (int i = 5; i <= 10; ++i) - setCharactersPositions(i); - _animator->setCharactersHeight(); - resetBrandonPoisonFlags(); - _screen->_curPage = 0; - // XXX - for (int i = 0; i < 12; ++i) { - int size = _screen->getRectSize(3, 24); - _shapes[361+i] = new byte[size]; - } - - _itemBkgBackUp[0] = new uint8[_screen->getRectSize(3, 24)]; - memset(_itemBkgBackUp[0], 0, _screen->getRectSize(3, 24)); - _itemBkgBackUp[1] = new uint8[_screen->getRectSize(4, 32)]; - memset(_itemBkgBackUp[1], 0, _screen->getRectSize(4, 32)); - - for (int i = 0; i < _roomTableSize; ++i) { - for (int item = 0; item < 12; ++item) { - _roomTable[i].itemsTable[item] = 0xFF; - _roomTable[i].itemsXPos[item] = 0xFFFF; - _roomTable[i].itemsYPos[item] = 0xFF; - _roomTable[i].needInit[item] = 0; +int KyraEngine_v1::init() { + registerDefaultSettings(); + + // Setup mixer + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); + + if (!_flags.useDigSound) { + // We prefer AdLib over native MIDI, since our AdLib playback code is much + // more mature than our MIDI player. For example we are missing MT-32 support + // and it seems our MIDI playback code has threading issues (see bug #1506583 + // "KYRA1: Crash on exceeded polyphony" for more information). + int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/); + + if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { + // TODO: currently we don't support the PC98 sound data, + // but since it has the FM-Towns data files, we just use the + // FM-Towns driver + if (_flags.gameID == GI_KYRA1) + _sound = new SoundTowns(this, _mixer); + else + _sound = new SoundTowns_v2(this, _mixer); + } else if (midiDriver == MD_ADLIB) { + _sound = new SoundAdlibPC(this, _mixer); + assert(_sound); + } else { + bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + + MidiDriver *driver = MidiDriver::createMidi(midiDriver); + assert(driver); + if (native_mt32) + driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + + SoundMidiPC *soundMidiPc = new SoundMidiPC(this, _mixer, driver); + _sound = soundMidiPc; + assert(_sound); + soundMidiPc->hasNativeMT32(native_mt32); + + // Unlike some SCUMM games, it's not that the MIDI sounds are + // missing. It's just that at least at the time of writing they + // are decidedly inferior to the Adlib ones. + if (ConfMan.getBool("multi_midi")) { + SoundAdlibPC *adlib = new SoundAdlibPC(this, _mixer); + assert(adlib); + + _sound = new MixedSoundDriver(this, _mixer, soundMidiPc, adlib); + assert(_sound); + } } } - loadCharacterShapes(); - loadSpecialEffectShapes(); - loadItems(); - loadButtonShapes(); - initMainButtonList(); - loadMainScreen(); - _screen->loadPalette("PALETTE.COL", _screen->_currentPalette); - - // XXX - _animator->initAnimStateList(); - setCharactersInDefaultScene(); - - if (!_emc->load("_STARTUP.EMC", &_npcScriptData, &_opcodes)) - error("Could not load \"_STARTUP.EMC\" script"); - _emc->init(&_scriptMain, &_npcScriptData); - - if (!_emc->start(&_scriptMain, 0)) - error("Could not start script function 0 of script \"_STARTUP.EMC\""); - - while (_emc->isValid(&_scriptMain)) - _emc->run(&_scriptMain); - - _emc->unload(&_npcScriptData); - - if (!_emc->load("_NPC.EMC", &_npcScriptData, &_opcodes)) - error("Could not load \"_NPC.EMC\" script"); - - snd_playTheme(1, -1); - if (_gameToLoad == -1) { - enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); - if (_abortIntroFlag && _skipIntroFlag) { - _menuDirectlyToLoad = true; - _screen->setMouseCursor(1, 1, _shapes[0]); - _screen->showMouse(); - _gui->buttonMenuCallback(0); - _menuDirectlyToLoad = false; - } else - saveGame(getSavegameFilename(0), "New game"); - } else { - _screen->setFont(Screen::FID_8_FNT); - loadGame(getSavegameFilename(_gameToLoad)); - _gameToLoad = -1; + if (_sound) + _sound->updateVolumeSettings(); + + _res = new Resource(this); + assert(_res); + _res->reset(); + _staticres = new StaticResource(this); + assert(_staticres); + if (!_staticres->init()) + error("_staticres->init() failed"); + if (!screen()->init()) + error("screen()->init() failed"); + _timer = new TimerManager(this, _system); + assert(_timer); + setupTimers(); + _emc = new EMCInterpreter(this); + assert(_emc); + + setupOpcodeTable(); + readSettings(); + + if (ConfMan.hasKey("save_slot")) { + _gameToLoad = ConfMan.getInt("save_slot"); + if (!saveFileLoadable(_gameToLoad)) + _gameToLoad = -1; } -} -void KyraEngine_v1::mainLoop() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::mainLoop()"); + _lang = 0; + Common::Language lang = Common::parseLanguage(ConfMan.get("language")); - while (!_quitFlag) { - int32 frameTime = (int32)_system->getMillis(); - _skipFlag = false; + if (_flags.gameID == GI_KYRA2 || _flags.gameID == GI_KYRA3) { + switch (lang) { + case Common::EN_ANY: + case Common::EN_USA: + case Common::EN_GRB: + _lang = 0; + break; - if (_currentCharacter->sceneId == 210) { - updateKyragemFading(); - if (seq_playEnd() && _deathHandler != 8) - break; - } + case Common::FR_FRA: + _lang = 1; + break; - if (_deathHandler != 0xFF) { - snd_playWanderScoreViaMap(0, 1); - snd_playSoundEffect(49); - _screen->hideMouse(); - _screen->setMouseCursor(1, 1, _shapes[0]); - destroyMouseItem(); - _screen->showMouse(); - _gui->buttonMenuCallback(0); - _deathHandler = 0xFF; - } + case Common::DE_DEU: + _lang = 2; + break; - if ((_brandonStatusBit & 2) && _brandonStatusBit0x02Flag) - _animator->animRefreshNPC(0); + case Common::JA_JPN: + _lang = 3; + break; - if ((_brandonStatusBit & 0x20) && _brandonStatusBit0x20Flag) { - _animator->animRefreshNPC(0); - _brandonStatusBit0x20Flag = 0; + default: + warning("unsupported language, switching back to English"); + _lang = 0; + break; } - - _screen->showMouse(); - - _gui->processButtonList(_buttonList, 0); - updateMousePointer(); - _timer->update(); - updateTextFade(); - - _handleInput = true; - delay((frameTime + _gameSpeed) - _system->getMillis(), true, true); - _handleInput = false; - - _sound->process(); } -} - -void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quitFlag) { - if (updateTimers) - _timer->update(); - if (timestamp - _system->getMillis() >= 10) - delay(10, update, isMainLoop); - } + return 0; } -void KyraEngine_v1::delay(uint32 amount, bool update, bool isMainLoop) { - Common::Event event; - - uint32 start = _system->getMillis(); - do { - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' && - (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && isMainLoop) { - const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990); - - if (event.kbd.flags == Common::KBD_CTRL) - loadGame(saveLoadSlot); - else { - char savegameName[14]; - sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); - saveGame(saveLoadSlot, savegameName); - } - } else if (event.kbd.flags == Common::KBD_CTRL) { - if (event.kbd.keycode == 'd') - _debugger->attach(); - else if (event.kbd.keycode == 'q') - _quitFlag = true; - } else if (event.kbd.keycode == '.') { - _skipFlag = true; - } else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) { - _abortIntroFlag = true; - _skipFlag = true; - } - - break; - case Common::EVENT_MOUSEMOVE: - _animator->_updateScreen = true; - break; - case Common::EVENT_QUIT: - quitGame(); - break; - case Common::EVENT_LBUTTONDOWN: - _mousePressFlag = true; - break; - case Common::EVENT_LBUTTONUP: - _mousePressFlag = false; - - if (_abortWalkFlag2) - _abortWalkFlag = true; - - if (_handleInput) { - _handleInput = false; - processInput(); - _handleInput = true; - } else - _skipFlag = true; - - break; - default: - break; - } - } - - if (_debugger->isAttached()) - _debugger->onFrame(); - - if (update) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - updateTextFade(); - updateMousePointer(); - } - - if (_currentCharacter && _currentCharacter->sceneId == 210 && update) - updateKyragemFading(); - - if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) - _skipFlag = false; - - if (amount > 0 && !_skipFlag && !_quitFlag) - _system->delayMillis(10); - - if (_skipFlag) - _sound->voiceStop(); - } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag); +KyraEngine_v1::~KyraEngine_v1() { + for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i) + delete *i; + _opcodes.clear(); + + delete _res; + delete _staticres; + delete _sound; + delete _text; + delete _timer; + delete _emc; + delete _debugger; } -void KyraEngine_v1::waitForEvent() { - bool finished = false; - Common::Event event; - - while (!finished && !_quitFlag) { - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - finished = true; - break; - case Common::EVENT_QUIT: - quitGame(); - break; - case Common::EVENT_LBUTTONDOWN: - finished = true; - _skipFlag = true; - break; - default: - break; - } - } - - if (_debugger->isAttached()) - _debugger->onFrame(); - - _system->delayMillis(10); - } +void KyraEngine_v1::quitGame() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::quitGame()"); + _quitFlag = true; + // Nothing to do here } -void KyraEngine_v1::delayWithTicks(int ticks) { - uint32 nextTime = _system->getMillis() + ticks * _tickLength; - - while (_system->getMillis() < nextTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); +Common::Point KyraEngine_v1::getMousePos() const { + Common::Point mouse = _eventMan->getMousePos(); - if (_currentCharacter->sceneId == 210) { - updateKyragemFading(); - seq_playEnd(); - } - - if (_skipFlag) - break; - - if (nextTime - _system->getMillis() >= 10) - delay(10); + if (_flags.useHiResOverlay) { + mouse.x >>= 1; + mouse.y >>= 1; } -} -#pragma mark - -#pragma mark - Animation/shape specific code -#pragma mark - - -void KyraEngine_v1::setupShapes123(const Shape *shapeTable, int endShape, int flags) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setupShapes123(%p, %d, %d)", (const void *)shapeTable, endShape, flags); - - for (int i = 123; i <= 172; ++i) - _shapes[i] = 0; - - uint8 curImage = 0xFF; - int curPageBackUp = _screen->_curPage; - _screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff - int shapeFlags = 2; - if (flags) - shapeFlags = 3; - for (int i = 123; i < 123+endShape; ++i) { - uint8 newImage = shapeTable[i-123].imageIndex; - if (newImage != curImage && newImage != 0xFF) { - assert(_characterImageTable); - _screen->loadBitmap(_characterImageTable[newImage], 8, 8, 0); - curImage = newImage; - } - _shapes[i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags); - assert(i-7 < _defaultShapeTableSize); - _defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset; - _defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset; - _defaultShapeTable[i-7].w = shapeTable[i-123].w; - _defaultShapeTable[i-7].h = shapeTable[i-123].h; - } - _screen->_curPage = curPageBackUp; + return mouse; } -void KyraEngine_v1::freeShapes123() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::freeShapes123()"); - - for (int i = 123; i <= 172; ++i) { - delete [] _shapes[i]; - _shapes[i] = 0; +void KyraEngine_v1::setMousePos(int x, int y) { + if (_flags.useHiResOverlay) { + x <<= 1; + y <<= 1; } + _system->warpMouse(x, y); } -#pragma mark - -#pragma mark - Misc stuff -#pragma mark - - -Movie *KyraEngine_v1::createWSAMovie() { - if (_flags.platform == Common::kPlatformAmiga) - return new WSAMovieAmiga(this); - - return new WSAMovieV1(this); +int KyraEngine_v1::setGameFlag(int flag) { + _flagsTable[flag >> 3] |= (1 << (flag & 7)); + return 1; } -void KyraEngine_v1::setBrandonPoisonFlags(int reset) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setBrandonPoisonFlags(%d)", reset); - _brandonStatusBit |= 1; - - if (reset) - _poisonDeathCounter = 0; - - for (int i = 0; i < 0x100; ++i) - _brandonPoisonFlagsGFX[i] = i; - - _brandonPoisonFlagsGFX[0x99] = 0x34; - _brandonPoisonFlagsGFX[0x9A] = 0x35; - _brandonPoisonFlagsGFX[0x9B] = 0x37; - _brandonPoisonFlagsGFX[0x9C] = 0x38; - _brandonPoisonFlagsGFX[0x9D] = 0x2B; +int KyraEngine_v1::queryGameFlag(int flag) const { + return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1); } -void KyraEngine_v1::resetBrandonPoisonFlags() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::resetBrandonPoisonFlags()"); - _brandonStatusBit = 0; - - for (int i = 0; i < 0x100; ++i) - _brandonPoisonFlagsGFX[i] = i; +int KyraEngine_v1::resetGameFlag(int flag) { + _flagsTable[flag >> 3] &= ~(1 << (flag & 7)); + return 0; } -#pragma mark - -#pragma mark - Input -#pragma mark - - -void KyraEngine_v1::processInput() { - Common::Point mouse = getMousePos(); - int xpos = mouse.x; - int ypos = mouse.y; - - debugC(9, kDebugLevelMain, "KyraEngine_v1::processInput(%d, %d)", xpos, ypos); - _abortWalkFlag2 = false; - - if (processInputHelper(xpos, ypos)) - return; - - uint8 item = findItemAtPos(xpos, ypos); - if (item == 0xFF) { - _changedScene = false; - int handled = clickEventHandler(xpos, ypos); - if (_changedScene || handled) - return; - } - - // XXX _deathHandler specific - if (ypos <= 158) { - uint16 exit = 0xFFFF; - if (xpos < 12) { - exit = _walkBlockWest; - } else if (xpos >= 308) { - exit = _walkBlockEast; - } else if (ypos >= 136) { - exit = _walkBlockSouth; - } else if (ypos < 12) { - exit = _walkBlockNorth; - } - - if (exit != 0xFFFF) { - _abortWalkFlag2 = true; - handleSceneChange(xpos, ypos, 1, 1); - _abortWalkFlag2 = false; - return; - } else { - int script = checkForNPCScriptRun(xpos, ypos); - if (script >= 0) { - runNpcScript(script); - return; - } - if (_itemInHand != -1) { - if (ypos < 155) { - if (hasClickedOnExit(xpos, ypos)) { - _abortWalkFlag2 = true; - handleSceneChange(xpos, ypos, 1, 1); - _abortWalkFlag2 = false; - return; - } - dropItem(0, _itemInHand, xpos, ypos, 1); - } - } else { - if (ypos <= 155) { - _abortWalkFlag2 = true; - handleSceneChange(xpos, ypos, 1, 1); - _abortWalkFlag2 = false; - } - } - } +void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { + while (_system->getMillis() < timestamp && !_quitFlag) { + if (timestamp - _system->getMillis() >= 10) + delay(10, update, isMainLoop); } } -int KyraEngine_v1::processInputHelper(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::processInputHelper(%d, %d)", xpos, ypos); - uint8 item = findItemAtPos(xpos, ypos); - if (item != 0xFF) { - if (_itemInHand == -1) { - _screen->hideMouse(); - _animator->animRemoveGameItem(item); - snd_playSoundEffect(53); - assert(_currentCharacter->sceneId < _roomTableSize); - Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; - int item2 = currentRoom->itemsTable[item]; - currentRoom->itemsTable[item] = 0xFF; - setMouseItem(item2); - assert(_itemList && _takenList); - updateSentenceCommand(_itemList[item2], _takenList[0], 179); - _itemInHand = item2; - _screen->showMouse(); - clickEventHandler2(); - return 1; - } else { - exchangeItemWithMouseItem(_currentCharacter->sceneId, item); - return 1; - } - } - return 0; +void KyraEngine_v1::delay(uint32 amount, bool update, bool isMainLoop) { + _system->delayMillis(amount); } -int KyraEngine_v1::clickEventHandler(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::clickEventHandler(%d, %d)", xpos, ypos); - _emc->init(&_scriptClick, &_scriptClickData); - _scriptClick.regs[1] = xpos; - _scriptClick.regs[2] = ypos; - _scriptClick.regs[3] = 0; - _scriptClick.regs[4] = _itemInHand; - _emc->start(&_scriptClick, 1); - - while (_emc->isValid(&_scriptClick)) - _emc->run(&_scriptClick); +void KyraEngine_v1::delayWithTicks(int ticks) { + delay(ticks * _tickLength); +} - return _scriptClick.regs[3]; +void KyraEngine_v1::registerDefaultSettings() { + if (_flags.gameID != GI_KYRA3) + ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)); } -void KyraEngine_v1::updateMousePointer(bool forceUpdate) { - int shape = 0; - - int newMouseState = 0; - int newX = 0; - int newY = 0; - Common::Point mouse = getMousePos(); - if (mouse.y <= 158) { - if (mouse.x >= 12) { - if (mouse.x >= 308) { - if (_walkBlockEast == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -5; - shape = 3; - newX = 7; - newY = 5; - } - } else if (mouse.y >= 136) { - if (_walkBlockSouth == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -4; - shape = 4; - newX = 5; - newY = 7; - } - } else if (mouse.y < 12) { - if (_walkBlockNorth == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -6; - shape = 2; - newX = 5; - newY = 1; - } - } - } else { - if (_walkBlockWest == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -3; - newX = 1; - newY = shape = 5; - } - } +void KyraEngine_v1::readSettings() { + _configWalkspeed = ConfMan.getInt("walkspeed"); + _configMusic = 0; + + if (!ConfMan.getBool("music_mute")) { + _configMusic = 1; + if (_flags.gameID != GI_KYRA3 && ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) + _configMusic = 2; } + _configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1; - if (mouse.x >= _entranceMouseCursorTracks[0] && mouse.y >= _entranceMouseCursorTracks[1] - && mouse.x <= _entranceMouseCursorTracks[2] && mouse.y <= _entranceMouseCursorTracks[3]) { - switch (_entranceMouseCursorTracks[4]) { - case 0: - newMouseState = -6; - shape = 2; - newX = 5; - newY = 1; - break; + if (_sound) { + _sound->enableMusic(_configMusic); + _sound->enableSFX(_configSounds); + } - case 2: - newMouseState = -5; - shape = 3; - newX = 7; - newY = 5; - break; + bool speechMute = ConfMan.getBool("speech_mute"); + bool subtitles = ConfMan.getBool("subtitles"); - case 4: - newMouseState = -4; - shape = 4; - newX = 5; - newY = 7; - break; + if (!speechMute && subtitles) + _configVoice = 2; // Voice & Text + else if (!speechMute && !subtitles) + _configVoice = 1; // Voice only + else + _configVoice = 0; // Text only - case 6: - newMouseState = -3; - shape = 5; - newX = 1; - newY = 5; - break; + setWalkspeed(_configWalkspeed); +} - default: - break; - } +void KyraEngine_v1::writeSettings() { + bool speechMute, subtitles; + + ConfMan.setInt("walkspeed", _configWalkspeed); + ConfMan.setBool("music_mute", _configMusic == 0); + if (_flags.gameID != GI_KYRA3) + ConfMan.setBool("cdaudio", _configMusic == 2); + ConfMan.setBool("sfx_mute", _configSounds == 0); + + switch (_configVoice) { + case 0: // Text only + speechMute = true; + subtitles = true; + break; + case 1: // Voice only + speechMute = false; + subtitles = false; + break; + default: // Voice & Text + speechMute = false; + subtitles = true; + break; } - if (newMouseState == -2) { - shape = 6; - newX = 4; - newY = 4; + if (_sound) { + if (!_configMusic) + _sound->beginFadeOut(); + _sound->enableMusic(_configMusic); + _sound->enableSFX(_configSounds); } - if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) { - _mouseState = newMouseState; - _screen->hideMouse(); - _screen->setMouseCursor(newX, newY, _shapes[shape]); - _screen->showMouse(); - } + ConfMan.setBool("speech_mute", speechMute); + ConfMan.setBool("subtitles", subtitles); - if (!newMouseState) { - if (_mouseState != _itemInHand || forceUpdate) { - if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) { - _mouseState = _itemInHand; - _screen->hideMouse(); - if (_itemInHand == -1) - _screen->setMouseCursor(1, 1, _shapes[0]); - else - _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]); - _screen->showMouse(); - } - } - } + ConfMan.flushToDisk(); } -bool KyraEngine_v1::hasClickedOnExit(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::hasClickedOnExit(%d, %d)", xpos, ypos); - if (xpos < 16 || xpos >= 304) - return true; - - if (ypos < 8) - return true; - - if (ypos < 136 || ypos > 155) - return false; - - return true; +bool KyraEngine_v1::speechEnabled() { + return _flags.isTalkie && (_configVoice == 1 || _configVoice == 2); } -void KyraEngine_v1::clickEventHandler2() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::clickEventHandler2()"); - - Common::Point mouse = getMousePos(); - - _emc->init(&_scriptClick, &_scriptClickData); - _scriptClick.regs[0] = _currentCharacter->sceneId; - _scriptClick.regs[1] = mouse.x; - _scriptClick.regs[2] = mouse.y; - _scriptClick.regs[4] = _itemInHand; - _emc->start(&_scriptClick, 6); - - while (_emc->isValid(&_scriptClick)) - _emc->run(&_scriptClick); +bool KyraEngine_v1::textEnabled() { + return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2); } -int KyraEngine_v1::checkForNPCScriptRun(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::checkForNPCScriptRun(%d, %d)", xpos, ypos); - int returnValue = -1; - const Character *currentChar = _currentCharacter; - int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0; - - int scaleFactor = _scaleTable[currentChar->y1]; - int addX = (((scaleFactor*8)*3)>>8)>>1; - int addY = ((scaleFactor*3)<<4)>>8; - - charLeft = currentChar->x1 - addX; - charRight = currentChar->x1 + addX; - charTop = currentChar->y1 - addY; - charBottom = currentChar->y1; - - if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos) - return 0; - - if (xpos > 304 || xpos < 16) - return -1; - - for (int i = 1; i < 5; ++i) { - currentChar = &_characterList[i]; - - if (currentChar->sceneId != _currentCharacter->sceneId) - continue; - - charLeft = currentChar->x1 - 12; - charRight = currentChar->x1 + 11; - charTop = currentChar->y1 - 48; - // if (!i) - // charBottom = currentChar->y2 - 16; - // else - charBottom = currentChar->y1; - - if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos) - continue; - - if (returnValue != -1) { - if (currentChar->y1 >= _characterList[returnValue].y1) - returnValue = i; - } else { - returnValue = i; - } - } - - return returnValue; +inline int convertValueToMixer(int value) { + value -= 2; + return (value * Audio::Mixer::kMaxMixerVolume) / 95; } -void KyraEngine_v1::runNpcScript(int func) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::runNpcScript(%d)", func); - _emc->init(&_npcScript, &_npcScriptData); - _emc->start(&_npcScript, func); - _npcScript.regs[0] = _currentCharacter->sceneId; - _npcScript.regs[4] = _itemInHand; - _npcScript.regs[5] = func; - - while (_emc->isValid(&_npcScript)) - _emc->run(&_npcScript); +inline int convertValueFromMixer(int value) { + return (value * 95) / Audio::Mixer::kMaxMixerVolume + 2; } -void KyraEngine_v1::checkAmuletAnimFlags() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::checkSpecialAnimFlags()"); - - if (_brandonStatusBit & 2) { - seq_makeBrandonNormal2(); - _timer->setCountdown(19, 300); - } +void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) { + switch (vol) { + case kVolumeMusic: + ConfMan.setInt("music_volume", convertValueToMixer(value)); + break; - if (_brandonStatusBit & 0x20) { - seq_makeBrandonNormal(); - _timer->setCountdown(19, 300); + case kVolumeSfx: + ConfMan.setInt("sfx_volume", convertValueToMixer(value)); + break; + + case kVolumeSpeech: + ConfMan.setInt("speech_volume", convertValueToMixer(value)); + break; } -} - -#pragma mark - - -void KyraEngine_v1::registerDefaultSettings() { - KyraEngine::registerDefaultSettings(); - - // Most settings already have sensible defaults. This one, however, is - // specific to the Kyra engine. - ConfMan.registerDefault("walkspeed", 2); -} - -void KyraEngine_v1::readSettings() { - int talkspeed = ConfMan.getInt("talkspeed"); - - // The default talk speed is 60. This should be mapped to "Normal". - - if (talkspeed == 0) - _configTextspeed = 3; // Clickable - if (talkspeed <= 50) - _configTextspeed = 0; // Slow - else if (talkspeed <= 150) - _configTextspeed = 1; // Normal - else - _configTextspeed = 2; // Fast - KyraEngine::readSettings(); + // Resetup mixer + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); + if (_sound) + _sound->updateVolumeSettings(); } -void KyraEngine_v1::writeSettings() { - int talkspeed; - - switch (_configTextspeed) { - case 0: // Slow - talkspeed = 1; - break; - case 1: // Normal - talkspeed = 60; +uint8 KyraEngine_v1::getVolume(kVolumeEntry vol) { + switch (vol) { + case kVolumeMusic: + return convertValueFromMixer(ConfMan.getInt("music_volume")); break; - case 2: // Fast - talkspeed = 255; + + case kVolumeSfx: + return convertValueFromMixer(ConfMan.getInt("sfx_volume")); break; - default: // Clickable - talkspeed = 0; + + case kVolumeSpeech: + if (speechEnabled()) + return convertValueFromMixer(ConfMan.getInt("speech_volume")); + else + return 2; break; } - ConfMan.setInt("talkspeed", talkspeed); - - KyraEngine::writeSettings(); + return 2; } -} // end of namespace Kyra +} // End of namespace Kyra + diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 50791c3ade..4f38ceca98 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -26,796 +26,281 @@ #ifndef KYRA_KYRA_V1_H #define KYRA_KYRA_V1_H -#include "kyra/kyra.h" +#include "engines/engine.h" + +#include "common/array.h" +#include "common/events.h" + #include "kyra/script.h" -#include "kyra/screen_v1.h" -#include "kyra/gui_v1.h" + +namespace Common { +class InSaveFile; +class OutSaveFile; +} // end of namespace Common + +class KyraMetaEngine; namespace Kyra { -class Movie; -class SoundDigital; -class SeqPlayer; -class Sprites; -class Debugger; -class Animator_v1; -class TextDisplayer; -class KyraEngine_v1; - -struct Character { - uint16 sceneId; - uint8 height; - uint8 facing; - uint16 currentAnimFrame; - uint8 inventoryItems[10]; - int16 x1, y1, x2, y2; -}; +struct GameFlags { + Common::Language lang; + Common::Platform platform; -struct Shape { - uint8 imageIndex; - int8 xOffset, yOffset; - uint8 x, y, w, h; -}; + bool isDemo : 1; + bool useAltShapeHeader : 1; // alternative shape header (uses 2 bytes more, those are unused though) + bool isTalkie : 1; + bool useHiResOverlay : 1; + bool useDigSound : 1; + bool useInstallerPackage : 1; -struct Room { - uint8 nameIndex; - uint16 northExit; - uint16 eastExit; - uint16 southExit; - uint16 westExit; - uint8 itemsTable[12]; - uint16 itemsXPos[12]; - uint8 itemsYPos[12]; - uint8 needInit[12]; + byte gameID; }; -struct Item { - uint8 unk1; - uint8 height; - uint8 unk2; - uint8 unk3; +enum { + GI_KYRA1 = 0, + GI_KYRA2 = 1, + GI_KYRA3 = 2 }; -struct SeqLoop { - const uint8 *ptr; - uint16 count; +struct AudioDataStruct { + const char * const *_fileList; + const int _fileListLen; + const void * const _cdaTracks; + const int _cdaNumTracks; }; -struct SceneExits { - uint16 northXPos; - uint8 northYPos; - uint16 eastXPos; - uint8 eastYPos; - uint16 southXPos; - uint8 southYPos; - uint16 westXPos; - uint8 westYPos; +// TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable +// in the future we maybe merge some flags and/or create new ones +enum kDebugLevels { + kDebugLevelScriptFuncs = 1 << 0, // prints debug output of o#_* functions + kDebugLevelScript = 1 << 1, // prints debug output of "EMCInterpreter" functions + kDebugLevelSprites = 1 << 2, // prints debug output of "Sprites" functions + kDebugLevelScreen = 1 << 3, // prints debug output of "Screen" functions + kDebugLevelSound = 1 << 4, // prints debug output of "Sound" functions + kDebugLevelAnimator = 1 << 5, // prints debug output of "ScreenAnimator" functions + kDebugLevelMain = 1 << 6, // prints debug output of common "KyraEngine(_v#)" functions && "TextDisplayer" functions + kDebugLevelGUI = 1 << 7, // prints debug output of "KyraEngine*" gui functions + kDebugLevelSequence = 1 << 8, // prints debug output of "SeqPlayer" functions + kDebugLevelMovie = 1 << 9, // prints debug output of movie specific funtions + kDebugLevelTimer = 1 << 10 // prints debug output of "TimerManager" functions }; -struct BeadState { - int16 x; - int16 y; - int16 width; - int16 height; - int16 dstX; - int16 dstY; - int16 width2; - int16 unk8; - int16 unk9; - int16 tableIndex; +enum kMusicDataID { + kMusicIntro = 0, + kMusicIngame, + kMusicFinale }; -class KyraEngine_v1 : public KyraEngine { - friend class MusicPlayer; - friend class Debugger_v1; - friend class Animator_v1; - friend class GUI_v1; +class Screen; +class Resource; +class Sound; +class Movie; +class TextDisplayer; +class StaticResource; +class TimerManager; +class Debugger; + +class KyraEngine_v1 : public Engine { +friend class Debugger; +friend class ::KyraMetaEngine; +friend class GUI; public: KyraEngine_v1(OSystem *system, const GameFlags &flags); - ~KyraEngine_v1(); + virtual ~KyraEngine_v1(); + + ::GUI::Debugger *getDebugger(); - Screen *screen() { return _screen; } - Animator_v1 *animator() { return _animator; } - virtual Movie *createWSAMovie(); + virtual void pauseEngineIntern(bool pause); - uint8 **shapes() { return _shapes; } - Character *currentCharacter() { return _currentCharacter; } - Character *characterList() { return _characterList; } - uint16 brandonStatus() { return _brandonStatusBit; } + bool quit() const { return _quitFlag; } - // TODO: remove me with workaround in animator.cpp l209 - uint16 getScene() { return _currentRoom; } + uint8 game() const { return _flags.gameID; } + const GameFlags &gameFlags() const { return _flags; } - int _paletteChanged; - int16 _northExitHeight; + // access to Kyra specific functionallity + Resource *resource() { return _res; } + virtual Screen *screen() = 0; + virtual TextDisplayer *text() { return _text; } + Sound *sound() { return _sound; } + StaticResource *staticres() { return _staticres; } + TimerManager *timer() { return _timer; } - typedef void (KyraEngine_v1::*IntroProc)(); + uint32 tickLength() const { return _tickLength; } - // static data access - const char * const*seqWSATable() { return _seq_WSATable; } - const char * const*seqCPSTable() { return _seq_CPSTable; } - const char * const*seqCOLTable() { return _seq_COLTable; } - const char * const*seqTextsTable() { return _seq_textsTable; } + Common::RandomSource _rnd; - const uint8 * const*palTable1() { return &_specialPalettes[0]; } - const uint8 * const*palTable2() { return &_specialPalettes[29]; } + // input + void setMousePos(int x, int y); + Common::Point getMousePos() const; + + // config specific + bool speechEnabled(); + bool textEnabled(); + + enum kVolumeEntry { + kVolumeMusic = 0, + kVolumeSfx = 1, + kVolumeSpeech = 2 + }; + + // volume reaches from 2 to 97 + void setVolume(kVolumeEntry vol, uint8 value); + uint8 getVolume(kVolumeEntry vol); + + // quit handling + virtual void quitGame(); + + // game flag handling + int setGameFlag(int flag); + int queryGameFlag(int flag) const; + int resetGameFlag(int flag); + + // sound + virtual void snd_playTheme(int file, int track); + virtual void snd_playSoundEffect(int id, int volume=0xFF); + virtual void snd_playWanderScoreViaMap(int command, int restart); + virtual void snd_playVoiceFile(int id) = 0; + virtual bool snd_voiceIsPlaying(); + virtual void snd_stopVoice(); + + // delay functionallity + virtual void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); + virtual void delay(uint32 millis, bool update = false, bool isMainLoop = false); + virtual void delayWithTicks(int ticks); protected: - virtual int go(); + virtual int go() = 0; virtual int init(); -public: - // sequences - // -> misc - bool seq_skipSequence() const; -protected: - // -> demo - void seq_demo(); - - // -> intro - void seq_intro(); - void seq_introLogos(); - void seq_introStory(); - void seq_introMalcolmTree(); - void seq_introKallakWriting(); - void seq_introKallakMalcolm(); - - // -> ingame animations - void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly); - void seq_brandonHealing(); - void seq_brandonHealing2(); - void seq_poisonDeathNow(int now); - void seq_poisonDeathNowAnim(); - void seq_playFluteAnimation(); - void seq_winterScroll1(); - void seq_winterScroll2(); - void seq_makeBrandonInv(); - void seq_makeBrandonNormal(); - void seq_makeBrandonNormal2(); - void seq_makeBrandonWisp(); - void seq_dispelMagicAnimation(); - void seq_fillFlaskWithWater(int item, int type); - void seq_playDrinkPotionAnim(int item, int unk2, int flags); - void seq_brandonToStone(); - - // -> end fight - int seq_playEnd(); - void seq_playEnding(); - - int handleMalcolmFlag(); - int handleBeadState(); - void initBeadState(int x, int y, int x2, int y2, int unk1, BeadState *ptr); - int processBead(int x, int y, int &x2, int &y2, BeadState *ptr); - - // -> credits - void seq_playCredits(); + // quit Handling + bool _quitFlag; -public: - // delay - void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); - void delay(uint32 millis, bool update = false, bool isMainLoop = false); - void delayWithTicks(int ticks); - void waitForEvent(); - - // TODO - void registerDefaultSettings(); - void readSettings(); - void writeSettings(); - - void snd_playSoundEffect(int track, int volume=0xFF); - void snd_playWanderScoreViaMap(int command, int restart); - virtual void snd_playVoiceFile(int id); - void snd_voiceWaitForFinish(bool ingame = true); + // intern + Resource *_res; + Sound *_sound; + TextDisplayer *_text; + StaticResource *_staticres; + TimerManager *_timer; + EMCInterpreter *_emc; + Debugger *_debugger; -protected: - void saveGame(const char *fileName, const char *saveName); - void loadGame(const char *fileName); + // config specific + virtual void registerDefaultSettings(); + virtual void readSettings(); + virtual void writeSettings(); -protected: - // input - void processInput(); - int processInputHelper(int xpos, int ypos); - int clickEventHandler(int xpos, int ypos); - void clickEventHandler2(); - void updateMousePointer(bool forceUpdate = false); - bool hasClickedOnExit(int xpos, int ypos); - - bool _skipFlag; - bool skipFlag() const { return _skipFlag; } - void resetSkipFlag(bool removeEvent = true) { _skipFlag = false; } - - // scene - // -> init - void loadSceneMsc(); - void startSceneScript(int brandonAlive); - void setupSceneItems(); - void initSceneData(int facing, int unk1, int brandonAlive); - void initSceneObjectList(int brandonAlive); - void initSceneScreen(int brandonAlive); - void setupSceneResource(int sceneId); - - // -> process - void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); - int handleSceneChange(int xpos, int ypos, int unk1, int frameReset); - int processSceneChange(int *table, int unk1, int frameReset); - int changeScene(int facing); - - // -> modification - void transcendScenes(int roomIndex, int roomName); - void setSceneFile(int roomIndex, int roomName); - - // -> pathfinder - int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); - bool lineIsPassable(int x, int y); - - // -> item handling - // --> misc - void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y); - - // --> drop handling - void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item); - int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2); - void dropItem(int unk1, int item, int x, int y, int unk2); - - // --> dropped item handling - int countItemsInScene(uint16 sceneId); - void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex); - byte findFreeItemInScene(int scene); - byte findItemAtPos(int x, int y); - - // --> drop area handling - void addToNoDropRects(int x, int y, int w, int h); - void clearNoDropRects(); - int isDropable(int x, int y); - int checkNoDropRects(int x, int y); - - // --> player items handling - void updatePlayerItemsForScene(); - - // --> item GFX handling - void backUpItemRect0(int xpos, int ypos); - void restoreItemRect0(int xpos, int ypos); - void backUpItemRect1(int xpos, int ypos); - void restoreItemRect1(int xpos, int ypos); + uint8 _configWalkspeed; - // items - // -> misc - void placeItemInGenericMapScene(int item, int index); - - // -> mouse item - void createMouseItem(int item); - void destroyMouseItem(); - void setMouseItem(int item); - - // -> graphics effects - void wipeDownMouseItem(int xpos, int ypos); - void itemSpecialFX(int x, int y, int item); - void itemSpecialFX1(int x, int y, int item); - void itemSpecialFX2(int x, int y, int item); - void magicOutMouseItem(int animIndex, int itemPos); - void magicInMouseItem(int animIndex, int item, int itemPos); - void specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops); - void processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops); - - // character - // -> movement - void moveCharacterToPos(int character, int facing, int xpos, int ypos); - void setCharacterPositionWithUpdate(int character); - int setCharacterPosition(int character, int *facingTable); - void setCharacterPositionHelper(int character, int *facingTable); - void setCharactersPositions(int character); - - // -> brandon - void setBrandonPoisonFlags(int reset); - void resetBrandonPoisonFlags(); - - // chat - // -> process - void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration); - void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum); - - // -> initialization - int initCharacterChat(int8 charNum); - void backupChatPartnerAnimFrame(int8 charNum); - void restoreChatPartnerAnimFrame(int8 charNum); - int8 getChatPartnerNum(); - - // -> deinitialization - void endCharacterChat(int8 charNum, int16 arg_4); - - // graphics - // -> misc - int findDuplicateItemShape(int shape); - void updateKyragemFading(); - - // -> interface - void loadMainScreen(int page = 3); - void redrawInventory(int page); -public: - void drawSentenceCommand(const char *sentence, int unk1); - void updateSentenceCommand(const char *str1, const char *str2, int unk1); - void updateTextFade(); + int _configMusic; + bool _configSounds; + uint8 _configVoice; -protected: - // -> amulet - void drawJewelPress(int jewel, int drawSpecial); - void drawJewelsFadeOutStart(); - void drawJewelsFadeOutEnd(int jewel); - - // -> shape handling - void setupShapes123(const Shape *shapeTable, int endShape, int flags); - void freeShapes123(); - - // misc (TODO) - void startup(); - void mainLoop(); - - int checkForNPCScriptRun(int xpos, int ypos); - void runNpcScript(int func); - - void loadMouseShapes(); - void loadCharacterShapes(); - void loadSpecialEffectShapes(); - void loadItems(); - void loadButtonShapes(); - void initMainButtonList(); - void setCharactersInDefaultScene(); - void setupPanPages(); - void freePanPages(); - void closeFinalWsa(); - - //void setTimer19(); - void setupTimers(); - void timerUpdateHeadAnims(int timerNum); - void timerSetFlags1(int timerNum); - void timerSetFlags2(int timerNum); - void timerSetFlags3(int timerNum); - void timerCheckAnimFlag1(int timerNum); - void timerCheckAnimFlag2(int timerNum); - void checkAmuletAnimFlags(); - void timerRedrawAmulet(int timerNum); - void timerFadeText(int timerNum); - void updateAnimFlag1(int timerNum); - void updateAnimFlag2(int timerNum); - void drawAmulet(); - void setTextFadeTimerCountdown(int16 countdown); - void setWalkspeed(uint8 newSpeed); - - int buttonInventoryCallback(Button *caller); - int buttonAmuletCallback(Button *caller); - - bool _skipIntroFlag; - bool _abortIntroFlag; - bool _menuDirectlyToLoad; - bool _abortWalkFlag; - bool _abortWalkFlag2; - bool _mousePressFlag; - uint8 *_itemBkgBackUp[2]; - uint8 *_shapes[373]; - int8 _itemInHand; - int _mouseState; - bool _handleInput; - bool _changedScene; - int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3; - int _beadStateVar; - int _unkAmuletVar; - - int _malcolmFlag; - int _endSequenceSkipFlag; - int _endSequenceNeedLoading; - int _unkEndSeqVar2; - uint8 *_endSequenceBackUpRect; - int _unkEndSeqVar4; - int _unkEndSeqVar5; - int _lastDisplayedPanPage; - uint8 *_panPagesTable[20]; - Movie *_finalA, *_finalB, *_finalC; - - Movie *_movieObjects[10]; - - uint16 _entranceMouseCursorTracks[8]; - uint16 _walkBlockNorth; - uint16 _walkBlockEast; - uint16 _walkBlockSouth; - uint16 _walkBlockWest; - - int32 _scaleMode; - int16 _scaleTable[145]; - - Rect _noDropRects[11]; - - int8 _birthstoneGemTable[4]; - int8 _idolGemsTable[3]; - - int8 _marbleVaseItem; - int8 _foyerItemTable[3]; - - int8 _cauldronState; - int8 _crystalState[2]; - - uint16 _brandonStatusBit; - uint8 _brandonStatusBit0x02Flag; - uint8 _brandonStatusBit0x20Flag; - uint8 _brandonPoisonFlagsGFX[256]; - uint8 _deathHandler; - int16 _brandonInvFlag; - uint8 _poisonDeathCounter; - int _brandonPosX; - int _brandonPosY; - - uint16 _currentChatPartnerBackupFrame; - uint16 _currentCharAnimFrame; - - int8 *_sceneAnimTable[50]; - - Item _itemTable[145]; - int _lastProcessedItem; - int _lastProcessedItemHeight; - - int16 *_exitListPtr; - int16 _exitList[11]; - SceneExits _sceneExits; - uint16 _currentRoom; - int _scenePhasingFlag; - - int _sceneChangeState; - int _loopFlag2; - - int _pathfinderFlag; - int _pathfinderFlag2; - int _lastFindWayRet; - int *_movFacingTable; - - int8 _talkingCharNum; - int8 _charSayUnk2; - int8 _charSayUnk3; - int8 _currHeadShape; - uint8 _currSentenceColor[3]; - int8 _startSentencePalIndex; - bool _fadeText; - - uint8 _configTextspeed; - - Animator_v1 *_animator; - SeqPlayer *_seq; - Sprites *_sprites; - Screen_v1 *_screen; - Debugger *_debugger; + // game speed + virtual bool skipFlag() const = 0; + virtual void resetSkipFlag(bool removeEvent = true) = 0; - EMCState _scriptMain; - - EMCState _npcScript; - EMCData _npcScriptData; - - EMCState _scriptClick; - EMCData _scriptClickData; - - Character *_characterList; - Character *_currentCharacter; - - Button *_buttonList; - GUI_v1 *_gui; - - struct KyragemState { - uint16 nextOperation; - uint16 rOffset; - uint16 gOffset; - uint16 bOffset; - uint32 timerCount; - } _kyragemFadingState; - - static const int8 _dosTrackMap[]; - static const int _dosTrackMapSize; - - // TODO: get rid of all variables having pointers to the static resources if possible - // i.e. let them directly use the _staticres functions - void initStaticResource(); - - const uint8 *_seq_Forest; - const uint8 *_seq_KallakWriting; - const uint8 *_seq_KyrandiaLogo; - const uint8 *_seq_KallakMalcolm; - const uint8 *_seq_MalcolmTree; - const uint8 *_seq_WestwoodLogo; - const uint8 *_seq_Demo1; - const uint8 *_seq_Demo2; - const uint8 *_seq_Demo3; - const uint8 *_seq_Demo4; - const uint8 *_seq_Reunion; - - const char * const*_seq_WSATable; - const char * const*_seq_CPSTable; - const char * const*_seq_COLTable; - const char * const*_seq_textsTable; - - int _seq_WSATable_Size; - int _seq_CPSTable_Size; - int _seq_COLTable_Size; - int _seq_textsTable_Size; - - const char * const*_itemList; - const char * const*_takenList; - const char * const*_placedList; - const char * const*_droppedList; - const char * const*_noDropList; - const char * const*_putDownFirst; - const char * const*_waitForAmulet; - const char * const*_blackJewel; - const char * const*_poisonGone; - const char * const*_healingTip; - const char * const*_thePoison; - const char * const*_fluteString; - const char * const*_wispJewelStrings; - const char * const*_magicJewelString; - const char * const*_flaskFull; - const char * const*_fullFlask; - const char * const*_veryClever; - const char * const*_homeString; - const char * const*_newGameString; - - int _itemList_Size; - int _takenList_Size; - int _placedList_Size; - int _droppedList_Size; - int _noDropList_Size; - int _putDownFirst_Size; - int _waitForAmulet_Size; - int _blackJewel_Size; - int _poisonGone_Size; - int _healingTip_Size; - int _thePoison_Size; - int _fluteString_Size; - int _wispJewelStrings_Size; - int _magicJewelString_Size; - int _flaskFull_Size; - int _fullFlask_Size; - int _veryClever_Size; - int _homeString_Size; - int _newGameString_Size; - - const char * const*_characterImageTable; - int _characterImageTableSize; - - const char * const*_guiStrings; - int _guiStringsSize; - - const char * const*_configStrings; - int _configStringsSize; - - Shape *_defaultShapeTable; - int _defaultShapeTableSize; - - const Shape *_healingShapeTable; - int _healingShapeTableSize; - const Shape *_healingShape2Table; - int _healingShape2TableSize; - - const Shape *_posionDeathShapeTable; - int _posionDeathShapeTableSize; - - const Shape *_fluteAnimShapeTable; - int _fluteAnimShapeTableSize; - - const Shape *_winterScrollTable; - int _winterScrollTableSize; - const Shape *_winterScroll1Table; - int _winterScroll1TableSize; - const Shape *_winterScroll2Table; - int _winterScroll2TableSize; - - const Shape *_drinkAnimationTable; - int _drinkAnimationTableSize; - - const Shape *_brandonToWispTable; - int _brandonToWispTableSize; - - const Shape *_magicAnimationTable; - int _magicAnimationTableSize; - - const Shape *_brandonStoneTable; - int _brandonStoneTableSize; - - Room *_roomTable; - int _roomTableSize; - const char * const*_roomFilenameTable; - int _roomFilenameTableSize; - - const uint8 *_amuleteAnim; - - const uint8 * const*_specialPalettes; - - const char *const *_soundFiles; - int _soundFilesSize; - const char *const *_soundFilesIntro; - int _soundFilesIntroSize; - const int32 *_cdaTrackTable; - int _cdaTrackTableSize; - const AudioDataStruct * _soundData; - - static const int8 _charXPosTable[]; - static const int8 _charYPosTable[]; - - // positions of the inventory - static const uint16 _itemPosX[]; - static const uint8 _itemPosY[]; - - void setupButtonData(); - Button *_buttonData; - Button **_buttonDataListPtr; - - static const uint8 _magicMouseItemStartFrame[]; - static const uint8 _magicMouseItemEndFrame[]; - static const uint8 _magicMouseItemStartFrame2[]; - static const uint8 _magicMouseItemEndFrame2[]; - - static const uint16 _amuletX[]; - static const uint16 _amuletY[]; - static const uint16 _amuletX2[]; - static const uint16 _amuletY2[]; -protected: - void setupOpcodeTable(); + uint16 _tickLength; + uint16 _gameSpeed; + + // run + int8 _deathHandler; + + // timer + virtual void setupTimers() = 0; + + virtual void setWalkspeed(uint8 speed) = 0; + + // detection + GameFlags _flags; + int _lang; + + // opcode + virtual void setupOpcodeTable() = 0; + Common::Array<const Opcode*> _opcodes; - // Opcodes - int o1_magicInMouseItem(EMCState *script); - int o1_characterSays(EMCState *script); - int o1_pauseTicks(EMCState *script); - int o1_drawSceneAnimShape(EMCState *script); int o1_queryGameFlag(EMCState *script); int o1_setGameFlag(EMCState *script); int o1_resetGameFlag(EMCState *script); - int o1_runNPCScript(EMCState *script); - int o1_setSpecialExitList(EMCState *script); - int o1_blockInWalkableRegion(EMCState *script); - int o1_blockOutWalkableRegion(EMCState *script); - int o1_walkPlayerToPoint(EMCState *script); - int o1_dropItemInScene(EMCState *script); - int o1_drawAnimShapeIntoScene(EMCState *script); - int o1_createMouseItem(EMCState *script); - int o1_savePageToDisk(EMCState *script); - int o1_sceneAnimOn(EMCState *script); - int o1_sceneAnimOff(EMCState *script); - int o1_getElapsedSeconds(EMCState *script); - int o1_mouseIsPointer(EMCState *script); - int o1_destroyMouseItem(EMCState *script); - int o1_runSceneAnimUntilDone(EMCState *script); - int o1_fadeSpecialPalette(EMCState *script); - int o1_playAdlibSound(EMCState *script); - int o1_playAdlibScore(EMCState *script); - int o1_phaseInSameScene(EMCState *script); - int o1_setScenePhasingFlag(EMCState *script); - int o1_resetScenePhasingFlag(EMCState *script); - int o1_queryScenePhasingFlag(EMCState *script); - int o1_sceneToDirection(EMCState *script); - int o1_setBirthstoneGem(EMCState *script); - int o1_placeItemInGenericMapScene(EMCState *script); - int o1_setBrandonStatusBit(EMCState *script); - int o1_pauseSeconds(EMCState *script); - int o1_getCharactersLocation(EMCState *script); - int o1_runNPCSubscript(EMCState *script); - int o1_magicOutMouseItem(EMCState *script); - int o1_internalAnimOn(EMCState *script); - int o1_forceBrandonToNormal(EMCState *script); - int o1_poisonDeathNow(EMCState *script); - int o1_setScaleMode(EMCState *script); - int o1_openWSAFile(EMCState *script); - int o1_closeWSAFile(EMCState *script); - int o1_runWSAFromBeginningToEnd(EMCState *script); - int o1_displayWSAFrame(EMCState *script); - int o1_enterNewScene(EMCState *script); - int o1_setSpecialEnterXAndY(EMCState *script); - int o1_runWSAFrames(EMCState *script); - int o1_popBrandonIntoScene(EMCState *script); - int o1_restoreAllObjectBackgrounds(EMCState *script); - int o1_setCustomPaletteRange(EMCState *script); - int o1_loadPageFromDisk(EMCState *script); - int o1_customPrintTalkString(EMCState *script); - int o1_restoreCustomPrintBackground(EMCState *script); + int o1_getRand(EMCState *script); int o1_hideMouse(EMCState *script); int o1_showMouse(EMCState *script); - int o1_getCharacterX(EMCState *script); - int o1_getCharacterY(EMCState *script); - int o1_changeCharactersFacing(EMCState *script); - int o1_copyWSARegion(EMCState *script); - int o1_printText(EMCState *script); - int o1_random(EMCState *script); - int o1_loadSoundFile(EMCState *script); - int o1_displayWSAFrameOnHidPage(EMCState *script); - int o1_displayWSASequentialFrames(EMCState *script); - int o1_drawCharacterStanding(EMCState *script); - int o1_internalAnimOff(EMCState *script); - int o1_changeCharactersXAndY(EMCState *script); - int o1_clearSceneAnimatorBeacon(EMCState *script); - int o1_querySceneAnimatorBeacon(EMCState *script); - int o1_refreshSceneAnimator(EMCState *script); - int o1_placeItemInOffScene(EMCState *script); - int o1_wipeDownMouseItem(EMCState *script); - int o1_placeCharacterInOtherScene(EMCState *script); - int o1_getKey(EMCState *script); - int o1_specificItemInInventory(EMCState *script); - int o1_popMobileNPCIntoScene(EMCState *script); - int o1_mobileCharacterInScene(EMCState *script); - int o1_hideMobileCharacter(EMCState *script); - int o1_unhideMobileCharacter(EMCState *script); - int o1_setCharactersLocation(EMCState *script); - int o1_walkCharacterToPoint(EMCState *script); - int o1_specialEventDisplayBrynnsNote(EMCState *script); - int o1_specialEventRemoveBrynnsNote(EMCState *script); - int o1_setLogicPage(EMCState *script); - int o1_fatPrint(EMCState *script); - int o1_preserveAllObjectBackgrounds(EMCState *script); - int o1_updateSceneAnimations(EMCState *script); - int o1_sceneAnimationActive(EMCState *script); - int o1_setCharactersMovementDelay(EMCState *script); - int o1_getCharactersFacing(EMCState *script); - int o1_bkgdScrollSceneAndMasksRight(EMCState *script); - int o1_dispelMagicAnimation(EMCState *script); - int o1_findBrightestFireberry(EMCState *script); - int o1_setFireberryGlowPalette(EMCState *script); - int o1_setDeathHandlerFlag(EMCState *script); - int o1_drinkPotionAnimation(EMCState *script); - int o1_makeAmuletAppear(EMCState *script); - int o1_drawItemShapeIntoScene(EMCState *script); - int o1_setCharactersCurrentFrame(EMCState *script); - int o1_waitForConfirmationMouseClick(EMCState *script); - int o1_pageFlip(EMCState *script); - int o1_setSceneFile(EMCState *script); - int o1_getItemInMarbleVase(EMCState *script); - int o1_setItemInMarbleVase(EMCState *script); - int o1_addItemToInventory(EMCState *script); - int o1_intPrint(EMCState *script); - int o1_shakeScreen(EMCState *script); - int o1_createAmuletJewel(EMCState *script); - int o1_setSceneAnimCurrXY(EMCState *script); - int o1_poisonBrandonAndRemaps(EMCState *script); - int o1_fillFlaskWithWater(EMCState *script); - int o1_getCharactersMovementDelay(EMCState *script); - int o1_getBirthstoneGem(EMCState *script); - int o1_queryBrandonStatusBit(EMCState *script); - int o1_playFluteAnimation(EMCState *script); - int o1_playWinterScrollSequence(EMCState *script); - int o1_getIdolGem(EMCState *script); - int o1_setIdolGem(EMCState *script); - int o1_totalItemsInScene(EMCState *script); - int o1_restoreBrandonsMovementDelay(EMCState *script); int o1_setMousePos(EMCState *script); + int o1_setHandItem(EMCState *script); + int o1_removeHandItem(EMCState *script); int o1_getMouseState(EMCState *script); - int o1_setEntranceMouseCursorTrack(EMCState *script); - int o1_itemAppearsOnGround(EMCState *script); - int o1_setNoDrawShapesFlag(EMCState *script); - int o1_fadeEntirePalette(EMCState *script); - int o1_itemOnGroundHere(EMCState *script); - int o1_queryCauldronState(EMCState *script); - int o1_setCauldronState(EMCState *script); - int o1_queryCrystalState(EMCState *script); - int o1_setCrystalState(EMCState *script); - int o1_setPaletteRange(EMCState *script); - int o1_shrinkBrandonDown(EMCState *script); - int o1_growBrandonUp(EMCState *script); - int o1_setBrandonScaleXAndY(EMCState *script); - int o1_resetScaleMode(EMCState *script); - int o1_getScaleDepthTableValue(EMCState *script); - int o1_setScaleDepthTableValue(EMCState *script); - int o1_message(EMCState *script); - int o1_checkClickOnNPC(EMCState *script); - int o1_getFoyerItem(EMCState *script); - int o1_setFoyerItem(EMCState *script); - int o1_setNoItemDropRegion(EMCState *script); - int o1_walkMalcolmOn(EMCState *script); - int o1_passiveProtection(EMCState *script); - int o1_setPlayingLoop(EMCState *script); - int o1_brandonToStoneSequence(EMCState *script); - int o1_brandonHealingSequence(EMCState *script); - int o1_protectCommandLine(EMCState *script); - int o1_pauseMusicSeconds(EMCState *script); - int o1_resetMaskRegion(EMCState *script); - int o1_setPaletteChangeFlag(EMCState *script); + int o1_setDeathHandler(EMCState *script); + int o1_playWanderScoreViaMap(EMCState *script); int o1_fillRect(EMCState *script); - int o1_dummy(EMCState *script); - int o1_vocUnload(EMCState *script); - int o1_vocLoad(EMCState *script); + int o1_blockInWalkableRegion(EMCState *script); + int o1_blockOutWalkableRegion(EMCState *script); + int o1_playSoundEffect(EMCState *script); + + // items + int _mouseState; + + virtual void setHandItem(uint16 item) = 0; + virtual void removeHandItem() = 0; + + // game flags + uint8 _flagsTable[100]; // TODO: check this value + + // sound + Common::String _speechFile; + + int _curMusicTheme; + int _curSfxFile; + int16 _lastMusicCommand; + + const int8 *_trackMap; + int _trackMapSize; + + // pathfinder + virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); + int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end); + int getFacingFromPointToPoint(int x, int y, int toX, int toY); + int getOppositeFacingDirection(int dir); + void changePosTowardsFacing(int &x, int &y, int facing); + int getMoveTableSize(int *moveTable); + virtual bool lineIsPassable(int x, int y) = 0; + + static const int8 _addXPosTable[]; + static const int8 _addYPosTable[]; + + // Character + + static const int8 _charAddXPosTable[]; + static const int8 _charAddYPosTable[]; + + // save/load + int _gameToLoad; + + const char *getSavegameFilename(int num); + bool saveFileLoadable(int slot); + + struct SaveHeader { + Common::String description; + uint32 version; + byte gameID; + uint32 flags; + + bool originalSave; // savegame from original interpreter + bool oldHeader; // old scummvm save header + }; + + enum kReadSaveHeaderError { + kRSHENoError = 0, + kRSHEInvalidType = 1, + kRSHEInvalidVersion = 2, + kRSHEIoError = 3 + }; + + static kReadSaveHeaderError readSaveHeader(Common::InSaveFile *file, SaveHeader &header); + + Common::InSaveFile *openSaveForReading(const char *filename, SaveHeader &header); + Common::OutSaveFile *openSaveForWriting(const char *filename, const char *saveName) const; }; -} // end of namespace Kyra +} // End of namespace Kyra #endif diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 176f8e4e2f..12da338843 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -29,7 +29,7 @@ namespace Kyra { -KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const EngineDesc &desc) : KyraEngine(system, flags), _desc(desc) { +KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const EngineDesc &desc) : KyraEngine_v1(system, flags), _desc(desc) { memset(&_sceneAnims, 0, sizeof(_sceneAnims)); memset(&_sceneAnimMovie, 0, sizeof(_sceneAnimMovie)); @@ -64,18 +64,25 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi memset(_hiddenItems, -1, sizeof(_hiddenItems)); - _debugger = 0; _screenBuffer = 0; + + memset(&_mainCharacter, 0, sizeof(_mainCharacter)); + memset(&_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); + + _pauseStart = 0; } KyraEngine_v2::~KyraEngine_v2() { - for (ShapeMap::iterator i = _gameShapes.begin(); i != _gameShapes.end(); ++i) { - delete[] i->_value; - i->_value = 0; + if (!(_flags.isDemo && !_flags.isTalkie)) { + for (ShapeMap::iterator i = _gameShapes.begin(); i != _gameShapes.end(); ++i) { + delete[] i->_value; + i->_value = 0; + } + _gameShapes.clear(); } - _gameShapes.clear(); delete[] _itemList; + delete[] _sceneList; _emc->unload(&_sceneScriptData); @@ -85,15 +92,50 @@ KyraEngine_v2::~KyraEngine_v2() { delete *i; _opcodesAnimation.clear(); - delete _debugger; delete[] _screenBuffer; } +void KyraEngine_v2::pauseEngineIntern(bool pause) { + KyraEngine_v1::pauseEngineIntern(pause); + + if (!pause) { + uint32 pausedTime = _system->getMillis() - _pauseStart; + + for (int i = 0; i < ARRAYSIZE(_sceneSpecialScriptsTimer); ++i) { + if (_sceneSpecialScriptsTimer[i]) + _sceneSpecialScriptsTimer[i] += pausedTime; + } + + } else { + _pauseStart = _system->getMillis(); + } +} + +void KyraEngine_v2::delay(uint32 amount, bool updateGame, bool isMainLoop) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::delay(%u, %d, %d)", amount, updateGame, isMainLoop); + + uint32 start = _system->getMillis(); + do { + if (updateGame) { + if (_chatText) + updateWithText(); + else + update(); + } else { + updateInput(); + } + + if (amount > 0) + _system->delayMillis(amount > 10 ? 10 : amount); + } while (!skipFlag() && _system->getMillis() < start + amount && !_quitFlag); +} + int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { debugC(9, kDebugLevelMain, "KyraEngine_v2::checkInput(%p, %d)", (const void*)buttonList, mainLoop); updateInput(); int keys = 0; + int8 mouseWheel = 0; while (_eventList.size()) { Common::Event event = *_eventList.begin(); @@ -135,6 +177,14 @@ int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { breakLoop = true; } break; + case Common::EVENT_WHEELUP: + mouseWheel = -1; + break; + + case Common::EVENT_WHEELDOWN: + mouseWheel = 1; + break; + default: break; } @@ -148,7 +198,7 @@ int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) { _eventList.erase(_eventList.begin()); } - return gui_v2()->processButtonList(buttonList, keys | 0x8000); + return gui_v2()->processButtonList(buttonList, keys | 0x8000, mouseWheel); } void KyraEngine_v2::updateInput() { @@ -178,6 +228,8 @@ void KyraEngine_v2::updateInput() { // fall through case Common::EVENT_LBUTTONUP: + case Common::EVENT_WHEELUP: + case Common::EVENT_WHEELDOWN: _eventList.push_back(event); break; @@ -223,20 +275,18 @@ void KyraEngine_v2::addShapeToPool(const uint8 *data, int realIndex, int shape) debugC(9, kDebugLevelMain, "KyraEngine_v2::addShapeToPool(%p, %d, %d)", data, realIndex, shape); remShapeFromPool(realIndex); _gameShapes[realIndex] = screen_v2()->makeShapeCopy(data, shape); - assert(_gameShapes[realIndex]); } void KyraEngine_v2::addShapeToPool(uint8 *shpData, int index) { debugC(9, kDebugLevelMain, "KyraEngine_v2::addShapeToPool(%p, %d)", shpData, index); remShapeFromPool(index); _gameShapes[index] = shpData; - assert(_gameShapes[index]); } void KyraEngine_v2::remShapeFromPool(int idx) { ShapeMap::iterator iter = _gameShapes.find(idx); if (iter != _gameShapes.end()) { - delete [] iter->_value; + delete[] iter->_value; iter->_value = 0; } } @@ -294,8 +344,8 @@ int KyraEngine_v2::updateCharPos(int *table, int force) { debugC(9, kDebugLevelMain, "KyraEngine_v2::updateCharPos(%p, %d)", (const void*)table, force); if (_updateCharPosNextUpdate > _system->getMillis() && !force) return 0; - _mainCharacter.x1 += _updateCharPosXTable[_mainCharacter.facing]; - _mainCharacter.y1 += _updateCharPosYTable[_mainCharacter.facing]; + _mainCharacter.x1 += _charAddXPosTable[_mainCharacter.facing]; + _mainCharacter.y1 += _charAddYPosTable[_mainCharacter.facing]; updateCharAnimFrame(0, table); _updateCharPosNextUpdate = _system->getMillis() + getCharacterWalkspeed() * _tickLength; return 1; diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index f0d26ca011..24f7aad614 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -26,7 +26,7 @@ #ifndef KYRA_KYRA_V2_H #define KYRA_KYRA_V2_H -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/gui.h" #include "kyra/wsamovie.h" @@ -35,10 +35,25 @@ namespace Kyra { +struct FrameControl { + uint16 index; + uint16 delay; +}; + +struct ItemAnimData_v2 { + int16 itemIndex; + uint8 numFrames; + const FrameControl *frames; +}; + +struct ActiveItemAnim { + uint16 currentFrame; + uint32 nextFrame; +}; + class Screen_v2; -class Debugger_v2; -class KyraEngine_v2 : public KyraEngine { +class KyraEngine_v2 : public KyraEngine_v1 { friend class Debugger_v2; friend class GUI_v2; public: @@ -52,23 +67,29 @@ public: // Animation script specific const int animScriptFrameAdd; + + // Item specific + const int maxItemId; }; KyraEngine_v2(OSystem *system, const GameFlags &flags, const EngineDesc &desc); ~KyraEngine_v2(); + virtual void pauseEngineIntern(bool pause); + virtual Screen_v2 *screen_v2() const = 0; virtual GUI *gui_v2() const = 0; + void delay(uint32 time, bool update = false, bool isMainLoop = false); + const EngineDesc &engineDesc() const { return _desc; } protected: EngineDesc _desc; - Debugger_v2 *_debugger; // run + uint32 _pauseStart; bool _runFlag; bool _showOutro; - int8 _deathHandler; virtual void update() = 0; virtual void updateWithText() = 0; @@ -211,7 +232,7 @@ protected: }; SceneAnim _sceneAnims[16]; - WSAMovieV2 *_sceneAnimMovie[16]; + WSAMovie_v2 *_sceneAnimMovie[16]; void freeSceneAnims(); @@ -299,7 +320,6 @@ protected: int _itemListSize; int _itemInHand; - int _handItemSet; int findFreeItem(); int countAllItems(); @@ -338,8 +358,6 @@ protected: void updateCharPosWithUpdate(); uint32 _updateCharPosNextUpdate; - static const int8 _updateCharPosXTable[]; - static const int8 _updateCharPosYTable[]; virtual int getCharacterWalkspeed() const = 0; virtual void updateCharAnimFrame(int num, int *table) = 0; @@ -374,22 +392,10 @@ protected: int o2_moveCharacter(EMCState *script); int o2_checkForItem(EMCState *script); int o2_defineItem(EMCState *script); - int o2_queryGameFlag(EMCState *script); - int o2_resetGameFlag(EMCState *script); - int o2_setGameFlag(EMCState *script); - int o2_setHandItem(EMCState *script); - int o2_removeHandItem(EMCState *script); - int o2_handItemSet(EMCState *script); - int o2_hideMouse(EMCState *script); int o2_addSpecialExit(EMCState *script); - int o2_setMousePos(EMCState *script); - int o2_showMouse(EMCState *script); int o2_delay(EMCState *script); int o2_update(EMCState *script); int o2_getShapeFlag1(EMCState *script); - int o2_playWanderScoreViaMap(EMCState *script); - int o2_getRand(EMCState *script); - int o2_setDeathHandler(EMCState *script); int o2_waitForConfirmationClick(EMCState *script); int o2_randomSceneChat(EMCState *script); int o2_setDlgIndex(EMCState *script); diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index aec2778def..ebb63b4b4e 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -1,49 +1,50 @@ MODULE := engines/kyra MODULE_OBJS := \ - animator_v1.o \ + animator_lok.o \ animator_v2.o \ animator_hof.o \ animator_mr.o \ debugger.o \ detection.o \ gui.o \ - gui_v1.o \ + gui_lok.o \ gui_v2.o \ gui_hof.o \ gui_mr.o \ - items_v1.o \ + items_lok.o \ items_v2.o \ items_hof.o \ items_mr.o \ - kyra.o \ kyra_v1.o \ + kyra_lok.o \ kyra_v2.o \ kyra_hof.o \ kyra_mr.o \ resource.o \ saveload.o \ - saveload_v1.o \ + saveload_lok.o \ saveload_hof.o \ saveload_mr.o \ - scene.o \ scene_v1.o \ + scene_lok.o \ scene_v2.o \ scene_hof.o \ scene_mr.o \ screen.o \ - screen_v1.o \ + screen_lok.o \ screen_v2.o \ screen_hof.o \ screen_mr.o \ script_v1.o \ + script_lok.o \ script_v2.o \ script_hof.o \ script_mr.o \ script.o \ script_tim.o \ seqplayer.o \ - sequences_v1.o \ + sequences_lok.o \ sequences_v2.o \ sequences_hof.o \ sequences_mr.o \ @@ -51,15 +52,15 @@ MODULE_OBJS := \ sound_digital.o \ sound_towns.o \ sound.o \ - sound_v1.o \ + sound_lok.o \ sprites.o \ staticres.o \ text.o \ - text_v1.o \ + text_lok.o \ text_hof.o \ text_mr.o \ timer.o \ - timer_v1.o \ + timer_lok.o \ timer_hof.o \ timer_mr.o \ vqa.o \ diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index b2564221fc..afd7eacfda 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -30,22 +30,24 @@ #include "common/fs.h" #include "common/func.h" -#include "gui/message.h" - #include "kyra/resource.h" namespace Kyra { -Resource::Resource(KyraEngine *vm) : _loaders(), _map(), _vm(vm) { +Resource::Resource(KyraEngine_v1 *vm) : _loaders(), _map(), _vm(vm) { initializeLoaders(); } Resource::~Resource() { _map.clear(); _loaders.clear(); + + clearCompFileList(); + _compLoaders.clear(); } bool Resource::reset() { + clearCompFileList(); unloadAllPakFiles(); FilesystemNode dir(ConfMan.get("path")); @@ -53,13 +55,10 @@ bool Resource::reset() { if (!dir.exists() || !dir.isDirectory()) error("invalid game path '%s'", dir.getPath().c_str()); - if (_vm->game() != GI_KYRA3) { - if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat()) { - Common::String errorMessage = "You're missing the '" + StaticResource::staticDataFilename() + "' file or it got corrupted, (re)get it from the ScummVM website"; - ::GUI::MessageDialog errorMsg(errorMessage); - errorMsg.runModal(); - error(errorMessage.c_str()); - } + if (!loadPakFile(StaticResource::staticDataFilename()) || !StaticResource::checkKyraDat()) { + Common::String errorMessage = "You're missing the '" + StaticResource::staticDataFilename() + "' file or it got corrupted, (re)get it from the ScummVM website"; + _vm->GUIErrorMessage(errorMessage); + error(errorMessage.c_str()); } if (_vm->game() == GI_KYRA1) { @@ -71,17 +70,32 @@ bool Resource::reset() { if (_vm->gameFlags().isTalkie) loadPakFile("CHAPTER1.VRM"); } else if (_vm->game() == GI_KYRA2) { + if (_vm->gameFlags().useInstallerPackage) + tryLoadCompFiles(); + // mouse pointer, fonts, etc. required for initializing if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) { loadPakFile("GENERAL.PAK"); } else { + if (_vm->gameFlags().isTalkie) { + // Add default file directories + Common::File::addDefaultDirectory(ConfMan.get("path") + "hof_cd"); + Common::File::addDefaultDirectory(ConfMan.get("path") + "HOF_CD"); + } + loadPakFile("INTROGEN.PAK"); loadPakFile("OTHER.PAK"); } return true; } else if (_vm->game() == GI_KYRA3) { - loadPakFile("WESTWOOD.001"); + if (_vm->gameFlags().useInstallerPackage) + loadPakFile("WESTWOOD.001"); + + // Add default file directories + Common::File::addDefaultDirectory(ConfMan.get("path") + "malcolm"); + Common::File::addDefaultDirectory(ConfMan.get("path") + "MALCOLM"); + loadFileList("FILEDATA.FDT"); return true; @@ -212,7 +226,7 @@ bool Resource::loadFileList(const Common::String &filedata) { buffer[12] = 0; f.seek(offset + 16, SEEK_SET); - Common::String filename = (char*)buffer; + Common::String filename = Common::String((char*)buffer); filename.toUppercase(); if (filename.hasSuffix(".PAK")) { @@ -253,6 +267,13 @@ void Resource::unloadPakFile(const Common::String &filename) { } } +void Resource::clearCompFileList() { + for (CompFileMap::iterator i = _compFiles.begin(); i != _compFiles.end(); ++i) + delete[] i->_value.data; + + _compFiles.clear(); +} + bool Resource::isInPakList(const Common::String &filename) { if (!isAccessable(filename)) return false; @@ -293,6 +314,8 @@ bool Resource::exists(const char *file, bool errorOutOnFail) { } uint32 Resource::getFileSize(const char *file) { + CompFileMap::iterator compEntry; + if (Common::File::exists(file)) { Common::File f; if (f.open(file)) @@ -314,12 +337,14 @@ bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) { return false; memset(buf, 0, maxSize); - stream->read(buf, stream->size()); + stream->read(buf, (maxSize <= stream->size()) ? maxSize : stream->size()); delete stream; return true; } Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) { + CompFileMap::iterator compEntry; + if (Common::File::exists(file)) { Common::File *stream = new Common::File(); if (!stream->open(file)) { @@ -328,6 +353,8 @@ Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) error("Couldn't open file '%s'", file.c_str()); } return stream; + } else if ((compEntry = _compFiles.find(file)) != _compFiles.end()) { + return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false); } else { if (!isAccessable(file)) return 0; @@ -376,19 +403,35 @@ bool Resource::isAccessable(const Common::String &file) { } void Resource::checkFile(const Common::String &file) { - if (_map.find(file) == _map.end() && Common::File::exists(file)) { - Common::File temp; - if (temp.open(file)) { + if (_map.find(file) == _map.end()) { + CompFileMap::const_iterator iter; + + if (Common::File::exists(file)) { + Common::File temp; + if (temp.open(file)) { + ResFileEntry entry; + entry.parent = ""; + entry.size = temp.size(); + entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; + entry.preload = false; + entry.prot = false; + entry.type = ResFileEntry::kAutoDetect; + entry.offset = 0; + _map[file] = entry; + temp.close(); + + detectFileTypes(); + } + } else if ((iter = _compFiles.find(file)) != _compFiles.end()) { ResFileEntry entry; entry.parent = ""; - entry.size = temp.size(); - entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; + entry.size = iter->_value.size; + entry.mounted = false; entry.preload = false; entry.prot = false; entry.type = ResFileEntry::kAutoDetect; entry.offset = 0; _map[file] = entry; - temp.close(); detectFileTypes(); } @@ -425,6 +468,13 @@ void Resource::detectFileTypes() { } } +void Resource::tryLoadCompFiles() { + for (CCompLoaderIterator i = _compLoaders.begin(); i != _compLoaders.end(); ++i) { + if ((*i)->checkForFiles()) + (*i)->loadFile(_compFiles); + } +} + #pragma mark - #pragma mark - ResFileLodaer #pragma mark - @@ -492,6 +542,20 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe return true; } +namespace { + +Common::String readString(Common::SeekableReadStream &stream) { + Common::String result; + char c = 0; + + while ((c = stream.readByte()) != 0) + result += c; + + return result; +} + +} // end of anonymous namespace + bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { uint32 filesize = stream.size(); @@ -559,6 +623,33 @@ bool ResLoaderPak::loadFile(const Common::String &filename, Common::SeekableRead startoffset = endoffset; } + FileList::const_iterator iter = Common::find(files.begin(), files.end(), Common::String("LINKLIST")); + if (iter != files.end()) { + stream.seek(iter->entry.offset, SEEK_SET); + + uint32 magic = stream.readUint32BE(); + + if (magic != MKID_BE('SCVM')) + error("LINKLIST file does not contain 'SCVM' header"); + + uint32 links = stream.readUint32BE(); + for (uint i = 0; i < links; ++i) { + Common::String linksTo = readString(stream); + uint32 sources = stream.readUint32BE(); + + iter = Common::find(files.begin(), files.end(), linksTo); + if (iter == files.end()) + error("PAK file link destination '%s' not found", linksTo.c_str()); + + for (uint j = 0; j < sources; ++j) { + Common::String dest = readString(stream); + files.push_back(File(dest, iter->entry)); + // Better safe than sorry, we update the 'iter' value, in case push_back invalidated it + iter = Common::find(files.begin(), files.end(), linksTo); + } + } + } + return true; } @@ -571,7 +662,7 @@ Common::SeekableReadStream *ResLoaderPak::loadFileFromArchive(const Common::Stri return stream; } -class ResLoaderIns : public ResArchiveLoader { +class ResLoaderInsMalcolm : public ResArchiveLoader { public: bool checkFilename(Common::String filename) const; bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const; @@ -579,16 +670,18 @@ public: Common::SeekableReadStream *loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const; ResFileEntry::kType getType() const { - return ResFileEntry::kIns; + return ResFileEntry::kInsMal; } }; -bool ResLoaderIns::checkFilename(Common::String filename) const { +bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const { filename.toUppercase(); - return (filename.hasSuffix(".001")); + if (!filename.hasSuffix(".001")) + return false; + return true; } -bool ResLoaderIns::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { +bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { stream.seek(3); uint32 size = stream.readUint32LE(); @@ -602,7 +695,7 @@ bool ResLoaderIns::isLoadable(const Common::String &filename, Common::SeekableRe return (buffer[0] == 0x0D && buffer[1] == 0x0A); } -bool ResLoaderIns::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { +bool ResLoaderInsMalcolm::loadFile(const Common::String &filename, Common::SeekableReadStream &stream, FileList &files) const { Common::List<Common::String> filenames; // thanks to eriktorbjorn for this code (a bit modified though) @@ -647,7 +740,7 @@ bool ResLoaderIns::loadFile(const Common::String &filename, Common::SeekableRead return true; } -Common::SeekableReadStream *ResLoaderIns::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const { +Common::SeekableReadStream *ResLoaderInsMalcolm::loadFileFromArchive(const Common::String &file, Common::SeekableReadStream *archive, const ResFileEntry entry) const { assert(archive); archive->seek(entry.offset, SEEK_SET); @@ -714,7 +807,7 @@ bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableRead entry.offset = resOffset+4; char realFilename[20]; - snprintf(realFilename, 20, "%u.AUD", resFilename); + snprintf(realFilename, 20, "%.08u.AUD", resFilename); uint32 curOffset = stream.pos(); stream.seek(resOffset, SEEK_SET); @@ -737,11 +830,669 @@ Common::SeekableReadStream *ResLoaderTlk::loadFileFromArchive(const Common::Stri } #pragma mark - +#pragma mark - CompFileLoader +#pragma mark - + +class FileExpanderSource { +public: + FileExpanderSource(const uint8 *data, int dataSize) : _dataPtr(data), _endofBuffer(data + dataSize), _bitsLeft(8), _key(0), _index(0) {} + ~FileExpanderSource() {} + + void advSrcRefresh(); + void advSrcBitsBy1(); + void advSrcBitsByIndex(uint8 newIndex); + + uint8 getKeyLower() { return _key & 0xff; } + void setIndex(uint8 index) { _index = index; } + uint16 getKeyMasked(uint8 newIndex); + uint16 keyMaskedAlign(uint16 val); + + void copyBytes(uint8 *& dst); + +private: + const uint8 *_dataPtr; + const uint8 *_endofBuffer; + uint16 _key; + int8 _bitsLeft; + uint8 _index; +}; + +void FileExpanderSource::advSrcBitsBy1() { + _key >>= 1; + if (!--_bitsLeft) { + if (_dataPtr < _endofBuffer) + _key = ((*_dataPtr++) << 8 ) | (_key & 0xff); + _bitsLeft = 8; + } +} + +void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) { + _index = newIndex; + _bitsLeft -= _index; + if (_bitsLeft <= 0) { + _key >>= (_index + _bitsLeft); + _index = -_bitsLeft; + _bitsLeft = 8 - _index; + if (_dataPtr < _endofBuffer) + _key = (*_dataPtr++ << 8) | (_key & 0xff); + } + _key >>= _index; +} + +uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) { + static const uint8 mskTable[] = { 0x0F, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; + _index = newIndex; + uint16 res = 0; + + if (_index > 8) { + newIndex = _index - 8; + res = (_key & 0xff) & mskTable[8]; + advSrcBitsByIndex(8); + _index = newIndex; + res |= (((_key & 0xff) & mskTable[_index]) << 8); + advSrcBitsByIndex(_index); + } else { + res = (_key & 0xff) & mskTable[_index]; + advSrcBitsByIndex(_index); + } + + return res; +} + +void FileExpanderSource::copyBytes(uint8 *& dst) { + advSrcBitsByIndex(_bitsLeft); + uint16 r = (READ_LE_UINT16(_dataPtr) ^ _key) + 1; + _dataPtr += 2; + + if (r) + error("decompression failure"); + + memcpy(dst, _dataPtr, _key); + _dataPtr += _key; + dst += _key; +} + +uint16 FileExpanderSource::keyMaskedAlign(uint16 val) { + val -= 0x101; + _index = (val & 0xff) >> 2; + int16 b = ((_bitsLeft << 8) | _index) - 1; + _bitsLeft = b >> 8; + _index = b & 0xff; + uint16 res = (((val & 3) + 4) << _index) + 0x101; + return res + getKeyMasked(_index); +} + +void FileExpanderSource::advSrcRefresh() { + _key = READ_LE_UINT16(_dataPtr); + if (_dataPtr < _endofBuffer - 1) + _dataPtr += 2; + _bitsLeft = 8; +} + +class FileExpander { +public: + FileExpander(); + ~FileExpander(); + + bool process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 insize); + +private: + void generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt); + uint8 calcCmdAndIndex(const uint8 *tbl, int16 ¶); + + FileExpanderSource *_src; + uint8 *_tables[9]; + uint16 *_tables16[3]; +}; + +FileExpander::FileExpander() : _src(0) { + _tables[0] = new uint8[3914]; + assert(_tables[0]); + + _tables[1] = _tables[0] + 320; + _tables[2] = _tables[0] + 352; + _tables[3] = _tables[0] + 864; + _tables[4] = _tables[0] + 2016; + _tables[5] = _tables[0] + 2528; + _tables[6] = _tables[0] + 2656; + _tables[7] = _tables[0] + 2736; + _tables[8] = _tables[0] + 2756; + + _tables16[0] = (uint16 *)(_tables[0] + 3268); + _tables16[1] = (uint16 *)(_tables[0] + 3302); + _tables16[2] = (uint16 *)(_tables[0] + 3338); +} + +FileExpander::~FileExpander() { + delete _src; + delete[] _tables[0]; +} + +bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 compressedSize) { + static const uint8 indexTable[] = { + 0x10, 0x11, 0x12, 0x00, 0x08, 0x07, 0x09, 0x06, 0x0A, + 0x05, 0x0B, 0x04, 0x0C, 0x03, 0x0D, 0x02, 0x0E, 0x01, 0x0F + }; + + memset(_tables[0], 0, 3914); + + uint8 *d = dst; + uint16 tableSize0 = 0; + uint16 tableSize1 = 0; + bool needrefresh = true; + bool postprocess = false; + + _src = new FileExpanderSource(src, compressedSize); + + while (d < dst + outsize) { + + if (needrefresh) { + needrefresh = false; + _src->advSrcRefresh(); + } + + _src->advSrcBitsBy1(); + + int mode = _src->getKeyMasked(2) - 1; + if (mode == 1) { + tableSize0 = _src->getKeyMasked(5) + 257; + tableSize1 = _src->getKeyMasked(5) + 1; + memset(_tables[7], 0, 19); + + const uint8 *itbl = indexTable; + int numbytes = _src->getKeyMasked(4) + 4; + + while (numbytes--) + _tables[7][*itbl++] = _src->getKeyMasked(3); + + generateTables(7, 8, 255, 19); + + int cnt = tableSize0 + tableSize1; + uint8 *tmp = _tables[0]; + + while (cnt) { + uint16 cmd = _src->getKeyLower(); + cmd = READ_LE_UINT16(&_tables[8][cmd << 1]); + _src->advSrcBitsByIndex(_tables[7][cmd]); + + if (cmd < 16) { + *tmp++ = cmd; + cnt--; + } else { + uint8 tmpI = 0; + if (cmd == 16) { + cmd = _src->getKeyMasked(2) + 3; + tmpI = *(tmp - 1); + } else if (cmd == 17) { + cmd = _src->getKeyMasked(3) + 3; + } else { + cmd = _src->getKeyMasked(7) + 11; + } + _src->setIndex(tmpI); + memset(tmp, tmpI, cmd); + tmp += cmd; + + cnt -= cmd; + if (cnt < 0) + error("decompression failure"); + } + } + + memcpy(_tables[1], _tables[0] + tableSize0, tableSize1); + generateTables(0, 2, 3, tableSize0); + generateTables(1, 4, 5, tableSize1); + postprocess = true; + } else if (mode < 0) { + _src->copyBytes(d); + postprocess = false; + needrefresh = true; + } else if (mode == 0){ + uint8 *d2 = _tables[0]; + memset(d2, 8, 144); + memset(d2 + 144, 9, 112); + memset(d2 + 256, 7, 24); + memset(d2 + 280, 8, 8); + d2 = _tables[1]; + memset(d2, 5, 32); + tableSize0 = 288; + tableSize1 = 32; + + generateTables(0, 2, 3, tableSize0); + generateTables(1, 4, 5, tableSize1); + postprocess = true; + } else { + error("decompression failure"); + } + + if (!postprocess) + continue; + + int16 cmd = 0; + + do { + cmd = ((int16*) _tables[2])[_src->getKeyLower()]; + _src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]); + + if (cmd == 0x11d) { + cmd = 0x200; + } else if (cmd > 0x108) { + cmd = _src->keyMaskedAlign(cmd); + } + + if (!(cmd >> 8)) { + *d++ = cmd & 0xff; + } else if (cmd != 0x100) { + cmd -= 0xfe; + int16 offset = ((int16*) _tables[4])[_src->getKeyLower()]; + _src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]); + if ((offset & 0xff) >= 4) { + uint8 newIndex = ((offset & 0xff) >> 1) - 1; + offset = (((offset & 1) + 2) << newIndex); + offset += _src->getKeyMasked(newIndex); + } + + uint8 *s2 = d - 1 - offset; + if (s2 >= dst) { + while (cmd--) + *d++ = *s2++; + } else { + uint32 pos = dst - s2; + s2 += (d - dst); + + if (pos < (uint32) cmd) { + cmd -= pos; + while (pos--) + *d++ = *s2++; + s2 = dst; + } + while (cmd--) + *d++ = *s2++; + } + } + } while (cmd != 0x100); + } + + delete _src; + _src = 0; + + return true; +} + +void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) { + const uint8 *tbl1 = _tables[srcIndex]; + const uint8 *tbl2 = _tables[dstIndex]; + const uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2]; + + if (!cnt) + return; + + const uint8 *s = tbl1; + memset(_tables16[0], 0, 32); + + for (int i = 0; i < cnt; i++) + _tables16[0][(*s++)]++; + + _tables16[1][1] = 0; + + for (uint16 i = 1, r = 0; i < 16; i++) { + r = (r + _tables16[0][i]) << 1; + _tables16[1][i + 1] = r; + } + + if (_tables16[1][16]) { + uint16 r = 0; + for (uint16 i = 1; i < 16; i++) + r += _tables16[0][i]; + if (r > 1) + error("decompression failure"); + } + + s = tbl1; + uint16 *d = _tables16[2]; + for (int i = 0; i < cnt; i++) { + uint16 t = *s++; + if (t) { + _tables16[1][t]++; + t = _tables16[1][t] - 1; + } + *d++ = t; + } + + s = tbl1; + d = _tables16[2]; + for (int i = 0; i < cnt; i++) { + int8 t = ((int8)(*s++)) - 1; + if (t > 0) { + uint16 v1 = *d; + uint16 v2 = 0; + + do { + v2 = (v2 << 1) | (v1 & 1); + v1 >>= 1; + } while (--t && v1); + + t++; + uint8 c1 = (v1 & 1); + while (t--) { + uint8 c2 = v2 >> 15; + v2 = (v2 << 1) | c1; + c1 = c2; + }; + + *d++ = v2; + } else { + d++; + } + } + + memset((void*) tbl2, 0, 512); + + cnt--; + s = tbl1 + cnt; + d = &_tables16[2][cnt]; + uint16 * bt = (uint16*) tbl3; + uint16 inc = 0; + uint16 cnt2 = 0; + + do { + uint8 t = *s--; + uint16 *s2 = (uint16*) tbl2; + + if (t && t < 9) { + inc = 1 << t; + uint16 o = *d; + + do { + s2[o] = cnt; + o += inc; + } while (!(o & 0xf00)); + + } else if (t > 8) { + if (!bt) + error("decompression failure"); + + t -= 8; + uint8 shiftCnt = 1; + uint8 v = (*d) >> 8; + s2 = &((uint16*) tbl2)[*d & 0xff]; + + do { + if (!*s2) { + *s2 = (uint16)(~cnt2); + *(uint32*)&bt[cnt2] = 0; + cnt2 += 2; + } + + s2 = &bt[(uint16)(~*s2)]; + if (v & shiftCnt) + s2++; + + shiftCnt <<= 1; + } while (--t); + *s2 = cnt; + } + d--; + } while (--cnt >= 0); +} + +uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 ¶) { + const uint16 *t = (const uint16*)tbl; + _src->advSrcBitsByIndex(8); + uint8 newIndex = 0; + uint16 v = _src->getKeyLower(); + + do { + newIndex++; + para = t[((~para) & 0xfffe) | (v & 1)]; + v >>= 1; + } while (para < 0); + + return newIndex; +} + +class CompLoaderInsHof : public CompArchiveLoader { +public: + bool checkForFiles() const; + bool loadFile(CompFileMap &loadTo) const; + +private: + struct Archive { + Common::String filename; + uint32 firstFile; + uint32 startOffset; + uint32 lastFile; + uint32 endOffset; + uint32 totalSize; + }; +}; + +bool CompLoaderInsHof::checkForFiles() const { + return (Common::File::exists("WESTWOOD.001") && Common::File::exists("WESTWOOD.002")); +} + +bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const { + Common::File tmpFile; + + uint32 pos = 0; + uint32 bytesleft = 0; + bool startFile = true; + + Common::String filenameBase = "WESTWOOD."; + Common::String filenameTemp; + char filenameExt[4]; + + while (filenameBase.lastChar() != '.') + filenameBase.deleteLastChar(); + + Archive newArchive; + + Common::List<Archive> archives; + + for (int8 currentFile = 1; currentFile; currentFile++) { + sprintf(filenameExt, "%03d", currentFile); + filenameTemp = filenameBase + Common::String(filenameExt); + + if (!tmpFile.open(filenameTemp)) { + debug(3, "couldn't open file '%s'\n", filenameTemp.c_str()); + break; + } + + tmpFile.seek(pos); + uint8 fileId = tmpFile.readByte(); + pos++; + + uint32 size = tmpFile.size() - 1; + if (startFile) { + size -= 4; + if (fileId == currentFile) { + size -= 6; + pos += 6; + tmpFile.seek(6, SEEK_CUR); + } else { + size = size + 1 - pos; + } + newArchive.filename = filenameBase; + bytesleft = newArchive.totalSize = tmpFile.readUint32LE(); + pos += 4; + newArchive.firstFile = currentFile; + newArchive.startOffset = pos; + startFile = false; + } + + uint32 cs = MIN(size, bytesleft); + bytesleft -= cs; + + tmpFile.close(); + + pos += cs; + if (cs == size) { + if (!bytesleft) { + newArchive.lastFile = currentFile; + newArchive.endOffset = --pos; + archives.push_back(newArchive); + currentFile = -1; + } else { + pos = 0; + } + } else { + startFile = true; + bytesleft = size - cs; + newArchive.lastFile = currentFile--; + newArchive.endOffset = --pos; + archives.push_back(newArchive); + } + } + + FileExpander exp; + CompFileEntry newEntry; + uint32 insize = 0; + uint32 outsize = 0; + uint8 *inbuffer = 0; + uint8 *outbuffer = 0; + uint32 inPart1 = 0; + uint32 inPart2 = 0; + Common::String entryStr; + + pos = 0; + + const uint32 kExecSize = 0x0bba; + const uint32 kHeaderSize = 30; + const uint32 kHeaderSize2 = 46; + + for (Common::List<Archive>::iterator a = archives.begin(); a != archives.end(); ++a) { + startFile = true; + for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) { + sprintf(filenameExt, "%03d", i); + filenameTemp = a->filename + Common::String(filenameExt); + + if (!tmpFile.open(filenameTemp)) { + debug(3, "couldn't open file '%s'\n", filenameTemp.c_str()); + break; + } + + uint32 size = (i == a->lastFile) ? a->endOffset : tmpFile.size(); + + if (startFile) { + startFile = false; + pos = a->startOffset + kExecSize; + if (pos > size) { + pos -= size; + tmpFile.close(); + continue; + } + } else { + if (inPart2) { + tmpFile.seek(1); + tmpFile.read(inbuffer + inPart1, inPart2); + inPart2 = 0; + exp.process(outbuffer, inbuffer, outsize, insize); + delete[] inbuffer; + inbuffer = 0; + newEntry.data = outbuffer; + newEntry.size = outsize; + loadTo[entryStr] = newEntry; + } + pos++; + } + + while (pos < size) { + uint8 hdr[43]; + uint32 m = 0; + tmpFile.seek(pos); + + if (pos + 42 > size) { + m = size - pos; + uint32 b = 42 - m; + + if (m >= 4) { + uint32 id = tmpFile.readUint32LE(); + if (id == 0x06054B50) { + startFile = true; + break; + } else { + tmpFile.seek(pos); + } + } + + sprintf(filenameExt, "%03d", i + 1); + filenameTemp = a->filename + Common::String(filenameExt); + + Common::File tmpFile2; + tmpFile2.open(filenameTemp); + tmpFile.read(hdr, m); + tmpFile2.read(hdr + m, b); + tmpFile2.close(); + + } else { + tmpFile.read(hdr, 42); + } + + uint32 id = READ_LE_UINT32(hdr); + + if (id == 0x04034B50) { + if (hdr[8] != 8) + error("compression type not implemented"); + insize = READ_LE_UINT32(hdr + 18); + outsize = READ_LE_UINT32(hdr + 22); + + uint16 filestrlen = READ_LE_UINT16(hdr + 26); + *(hdr + 30 + filestrlen) = 0; + entryStr = Common::String((const char *)(hdr + 30)); + pos += (kHeaderSize + filestrlen - m); + tmpFile.seek(pos); + + outbuffer = new uint8[outsize]; + if (!outbuffer) + error("Out of memory: Can't uncompress installer files"); + + if (!inbuffer) { + inbuffer = new uint8[insize]; + if (!inbuffer) + error("Out of memory: Can't uncompress installer files"); + } + + if ((pos + insize) > size) { + // this is for files that are split between two archive files + inPart1 = size - pos; + inPart2 = insize - inPart1; + tmpFile.read(inbuffer, inPart1); + } else { + tmpFile.read(inbuffer, insize); + inPart2 = 0; + exp.process(outbuffer, inbuffer, outsize, insize); + delete[] inbuffer; + inbuffer = 0; + newEntry.data = outbuffer; + newEntry.size = outsize; + loadTo[entryStr] = newEntry; + } + + pos += insize; + if (pos > size) { + pos -= size; + break; + } + } else { + uint32 filestrlen = READ_LE_UINT32(hdr + 28); + pos += (kHeaderSize2 + filestrlen - m); + } + } + tmpFile.close(); + } + } + + archives.clear(); + return true; +} + +#pragma mark - void Resource::initializeLoaders() { _loaders.push_back(LoaderList::value_type(new ResLoaderPak())); - _loaders.push_back(LoaderList::value_type(new ResLoaderIns())); + _loaders.push_back(LoaderList::value_type(new ResLoaderInsMalcolm())); _loaders.push_back(LoaderList::value_type(new ResLoaderTlk())); + + _compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsHof())); } const ResArchiveLoader *Resource::getLoader(ResFileEntry::kType type) const { @@ -755,3 +1506,4 @@ const ResArchiveLoader *Resource::getLoader(ResFileEntry::kType type) const { } // end of namespace Kyra + diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index f414cacee8..d43f730e6b 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -36,7 +36,7 @@ #include "common/stream.h" #include "common/ptr.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_hof.h" namespace Kyra { @@ -52,7 +52,7 @@ struct ResFileEntry { enum kType { kRaw = 0, kPak = 1, - kIns = 2, + kInsMal = 2, kTlk = 3, kAutoDetect }; @@ -60,7 +60,13 @@ struct ResFileEntry { uint32 offset; }; +struct CompFileEntry { + uint32 size; + uint8 *data; +}; + typedef Common::HashMap<Common::String, ResFileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ResFileMap; +typedef Common::HashMap<Common::String, CompFileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CompFileMap; class Resource; class ResArchiveLoader { @@ -69,6 +75,10 @@ public: File() : filename(), entry() {} File(const Common::String &f, const ResFileEntry &e) : filename(f), entry(e) {} + bool operator ==(const Common::String &r) const { + return filename.equalsIgnoreCase(r); + } + Common::String filename; ResFileEntry entry; }; @@ -86,9 +96,17 @@ public: protected: }; +class CompArchiveLoader { +public: + virtual ~CompArchiveLoader() {} + + virtual bool checkForFiles() const = 0; + virtual bool loadFile(CompFileMap &loadTo) const = 0; +}; + class Resource { public: - Resource(KyraEngine *vm); + Resource(KyraEngine_v1 *vm); ~Resource(); bool reset(); @@ -122,89 +140,97 @@ protected: LoaderList _loaders; ResFileMap _map; - KyraEngine *_vm; + typedef Common::List<Common::SharedPtr<CompArchiveLoader> > CompLoaderList; + typedef CompLoaderList::iterator CompLoaderIterator; + typedef CompLoaderList::const_iterator CCompLoaderIterator; + CompLoaderList _compLoaders; + CompFileMap _compFiles; + + void tryLoadCompFiles(); + void clearCompFileList(); + + KyraEngine_v1 *_vm; }; -// TODO?: maybe prefix all things here with 'kKyra1' instead of 'k' enum kKyraResources { kLoadAll = -1, - kForestSeq, - kKallakWritingSeq, - kKyrandiaLogoSeq, - kKallakMalcolmSeq, - kMalcolmTreeSeq, - kWestwoodLogoSeq, + k1ForestSeq, + k1KallakWritingSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, - kDemo1Seq, - kDemo2Seq, - kDemo3Seq, - kDemo4Seq, + k1Demo1Seq, + k1Demo2Seq, + k1Demo3Seq, + k1Demo4Seq, - kAmuleteAnimSeq, + k1AmuleteAnimSeq, - kOutroReunionSeq, + k1OutroReunionSeq, - kIntroCPSStrings, - kIntroCOLStrings, - kIntroWSAStrings, - kIntroStrings, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, - kOutroHomeString, + k1OutroHomeString, - kRoomFilenames, - kRoomList, + k1RoomFilenames, + k1RoomList, - kCharacterImageFilenames, + k1CharacterImageFilenames, - kItemNames, - kTakenStrings, - kPlacedStrings, - kDroppedStrings, - kNoDropStrings, + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, - kPutDownString, - kWaitAmuletString, - kBlackJewelString, - kPoisonGoneString, - kHealingTipString, - kWispJewelStrings, - kMagicJewelStrings, + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1PoisonGoneString, + k1HealingTipString, + k1WispJewelStrings, + k1MagicJewelStrings, - kThePoisonStrings, - kFluteStrings, + k1ThePoisonStrings, + k1FluteStrings, - kFlaskFullString, - kFullFlaskString, + k1FlaskFullString, + k1FullFlaskString, - kVeryCleverString, - kNewGameString, + k1VeryCleverString, + k1NewGameString, - kDefaultShapes, - kHealing1Shapes, - kHealing2Shapes, - kPoisonDeathShapes, - kFluteShapes, - kWinter1Shapes, - kWinter2Shapes, - kWinter3Shapes, - kDrinkShapes, - kWispShapes, - kMagicAnimShapes, - kBranStoneShapes, + k1DefaultShapes, + k1Healing1Shapes, + k1Healing2Shapes, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, - kPaletteList, + k1PaletteList, - kGUIStrings, - kConfigStrings, + k1GUIStrings, + k1ConfigStrings, - kAudioTracks, - kAudioTracksIntro, + k1AudioTracks, + k1AudioTracksIntro, - kKyra1TownsSFXwdTable, - kKyra1TownsSFXbtTable, - kKyra1TownsCDATable, - kCreditsStrings, + k1TownsSFXwdTable, + k1TownsSFXbtTable, + k1TownsCDATable, + k1CreditsStrings, k2SeqplayPakFiles, k2SeqplayCredits, @@ -229,6 +255,15 @@ enum kKyraResources { k2IngameShapeAnimData, k2IngameTlkDemoStrings, + k3MainMenuStrings, + k3MusicFiles, + k3ScoreTable, + k3SfxFiles, + k3SfxMap, + k3ItemAnimData, + k3ItemMagicTable, + k3ItemStringMap, + kMaxResIDs }; @@ -239,7 +274,7 @@ class StaticResource { public: static const Common::String staticDataFilename() { return "kyra.dat"; } - StaticResource(KyraEngine *vm) : _vm(vm), _resList(), _fileLoader(0), _builtIn(0), _filenameTable(0) {} + StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _builtIn(0), _filenameTable(0) {} ~StaticResource() { deinit(); } static bool checkKyraDat(); @@ -253,8 +288,8 @@ public: const Room *loadRoomTable(int id, int &entries); const uint8 * const*loadPaletteTable(int id, int &entries); const HofSeqData *loadHofSequenceData(int id, int &entries); - const ItemAnimData_v1 *loadHofShapeAnimDataV1(int id, int &entries); - const ItemAnimData_v2 *loadHofShapeAnimDataV2(int id, int &entries); + const ItemAnimData_v1 *loadShapeAnimData_v1(int id, int &entries); + const ItemAnimData_v2 *loadShapeAnimData_v2(int id, int &entries); // use '-1' to prefetch/unload all ids // prefetchId retruns false if only on of the resources @@ -263,9 +298,9 @@ public: bool prefetchId(int id); void unloadId(int id); private: - void outputError(); + void outputError(const Common::String &error); - KyraEngine *_vm; + KyraEngine_v1 *_vm; struct FilenameTable; struct ResData; @@ -284,8 +319,8 @@ private: bool loadRoomTable(const char *filename, void *&ptr, int &size); bool loadPaletteTable(const char *filename, void *&ptr, int &size); bool loadHofSequenceData(const char *filename, void *&ptr, int &size); - bool loadHofShapeAnimDataV1(const char *filename, void *&ptr, int &size); - bool loadHofShapeAnimDataV2(const char *filename, void *&ptr, int &size); + bool loadShapeAnimData_v1(const char *filename, void *&ptr, int &size); + bool loadShapeAnimData_v2(const char *filename, void *&ptr, int &size); void freeRawData(void *&ptr, int &size); void freeStringTable(void *&ptr, int &size); @@ -354,3 +389,4 @@ private: + diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index fa3266685f..22f934ba69 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -27,9 +27,9 @@ #include "common/savefile.h" #include "common/system.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" -#define CURRENT_SAVE_VERSION 11 +#define CURRENT_SAVE_VERSION 13 #define GF_FLOPPY (1 << 0) #define GF_TALKIE (1 << 1) @@ -37,7 +37,7 @@ namespace Kyra { -KyraEngine::kReadSaveHeaderError KyraEngine::readSaveHeader(Common::InSaveFile *in, SaveHeader &header) { +KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::InSaveFile *in, SaveHeader &header) { uint32 type = in->readUint32BE(); header.originalSave = false; header.oldHeader = false; @@ -70,6 +70,11 @@ KyraEngine::kReadSaveHeaderError KyraEngine::readSaveHeader(Common::InSaveFile * header.description = descriptionBuffer; header.gameID = GI_KYRA2; break; + } else if (type == MKID_BE('MBL4') && header.version == 102) { + saveOk = true; + header.description = descriptionBuffer; + header.gameID = GI_KYRA3; + break; } } @@ -103,14 +108,14 @@ KyraEngine::kReadSaveHeaderError KyraEngine::readSaveHeader(Common::InSaveFile * return (in->ioFailed() ? kRSHEIoError : kRSHENoError); } -Common::InSaveFile *KyraEngine::openSaveForReading(const char *filename, SaveHeader &header) { - debugC(9, kDebugLevelMain, "KyraEngine::openSaveForReading('%s', -)", filename); +Common::InSaveFile *KyraEngine_v1::openSaveForReading(const char *filename, SaveHeader &header) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForReading('%s', -)", filename); Common::InSaveFile *in = 0; if (!(in = _saveFileMan->openForLoading(filename))) return 0; - kReadSaveHeaderError errorCode = KyraEngine::readSaveHeader(in, header); + kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, header); if (errorCode != kRSHENoError) { if (errorCode == kRSHEInvalidType) warning("No ScummVM Kyra engine savefile header."); @@ -154,8 +159,8 @@ Common::InSaveFile *KyraEngine::openSaveForReading(const char *filename, SaveHea return in; } -Common::OutSaveFile *KyraEngine::openSaveForWriting(const char *filename, const char *saveName) const { - debugC(9, kDebugLevelMain, "KyraEngine::openSaveForWriting('%s', '%s')", filename, saveName); +Common::OutSaveFile *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName) const { + debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s')", filename, saveName); if (_quitFlag) return 0; @@ -186,7 +191,7 @@ Common::OutSaveFile *KyraEngine::openSaveForWriting(const char *filename, const return out; } -const char *KyraEngine::getSavegameFilename(int num) { +const char *KyraEngine_v1::getSavegameFilename(int num) { static Common::String filename; assert(num >= 0 && num <= 999); @@ -199,7 +204,7 @@ const char *KyraEngine::getSavegameFilename(int num) { return filename.c_str(); } -bool KyraEngine::saveFileLoadable(int slot) { +bool KyraEngine_v1::saveFileLoadable(int slot) { if (slot < 0 || slot > 999) return false; diff --git a/engines/kyra/saveload_v1.cpp b/engines/kyra/saveload_lok.cpp index 7e871876a0..8af73acc61 100644 --- a/engines/kyra/saveload_v1.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -27,16 +27,16 @@ #include "common/savefile.h" #include "common/system.h" -#include "kyra/kyra_v1.h" -#include "kyra/animator_v1.h" +#include "kyra/kyra_lok.h" +#include "kyra/animator_lok.h" #include "kyra/screen.h" #include "kyra/resource.h" #include "kyra/sound.h" #include "kyra/timer.h" namespace Kyra { -void KyraEngine_v1::loadGame(const char *fileName) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::loadGame('%s')", fileName); +void KyraEngine_LoK::loadGame(const char *fileName) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::loadGame('%s')", fileName); SaveHeader header; Common::InSaveFile *in = openSaveForReading(fileName, header); @@ -183,7 +183,7 @@ void KyraEngine_v1::loadGame(const char *fileName) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 8, 0); } - createMouseItem(_itemInHand); + setHandItem(_itemInHand); _animator->setBrandonAnimSeqSize(3, 48); redrawInventory(0); _animator->_noDrawShapesFlag = 1; @@ -218,8 +218,8 @@ void KyraEngine_v1::loadGame(const char *fileName) { delete in; } -void KyraEngine_v1::saveGame(const char *fileName, const char *saveName) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::saveGame('%s', '%s')", fileName, saveName); +void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s')", fileName, saveName); if (_quitFlag) return; diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp index 8b727862a5..51efc33723 100644 --- a/engines/kyra/saveload_mr.cpp +++ b/engines/kyra/saveload_mr.cpp @@ -49,15 +49,16 @@ void KyraEngine_MR::saveGame(const char *fileName, const char *saveName) { out->writeSint16BE(_lastMusicCommand); out->writeByte(_currentChapter); out->writeByte(_characterShapeFile); - //XXX + out->writeByte(_album.curPage); out->writeSint16BE(_score); out->writeSint16BE(_scoreMax); out->writeByte(_malcolmsMood); - out->write(_conversationState, sizeof(_conversationState)); - out->write(_newSceneDlgState, sizeof(_newSceneDlgState)); + for (int i = 0; i < 30; ++i) + out->write(_conversationState[i], 30); + out->write(_newSceneDlgState, 40); for (int i = 0; i < 100; ++i) out->writeUint16BE(_hiddenItems[i]); - out->write(_scoreFlagTable, sizeof(_scoreFlagTable)); + out->write(_scoreFlagTable, 26); out->writeUint16BE(_mainCharacter.sceneId); out->writeSint16BE(_mainCharacter.dlgIndex); @@ -88,6 +89,7 @@ void KyraEngine_MR::saveGame(const char *fileName, const char *saveName) { out->writeSint16BE(_talkObjectList[i].x); out->writeSint16BE(_talkObjectList[i].y); out->writeByte(_talkObjectList[i].color); + out->writeByte(_talkObjectList[i].sceneId); } for (int i = 0; i < 98; ++i) { @@ -129,6 +131,9 @@ void KyraEngine_MR::loadGame(const char *fileName) { return; } + if (header.originalSave) + warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported"); + if (_inventoryState) { updateCharacterAnim(0); restorePage3(); @@ -148,32 +153,58 @@ void KyraEngine_MR::loadGame(const char *fileName) { _screen->hideMouse(); - _timer->loadDataFromFile(in, header.version); + if (!header.originalSave) { + _timer->loadDataFromFile(in, header.version); - uint32 flagsSize = in.readUint32BE(); - assert(flagsSize <= sizeof(_flagsTable)); - in.read(_flagsTable, flagsSize); + uint32 flagsSize = in.readUint32BE(); + assert(flagsSize <= sizeof(_flagsTable)); + in.read(_flagsTable, flagsSize); + } - // usually we have to save the flag set by opcode 10 here _lastMusicCommand = in.readSint16(); _currentChapter = in.readByte(); _characterShapeFile = in.readByte(); - //XXX + + if (header.version >= 12 || header.originalSave) + _album.curPage = in.readByte(); + if (header.originalSave) + in.readByte(); + _score = in.readSint16(); _scoreMax = in.readSint16(); _malcolmsMood = in.readByte(); - in.read(_conversationState, sizeof(_conversationState)); - in.read(_newSceneDlgState, sizeof(_newSceneDlgState)); + + if (header.originalSave) + in.seek(8, SEEK_CUR); + + for (int i = 0; i < 30; ++i) + in.read(_conversationState[i], 30); + + if (!header.originalSave) { + in.read(_newSceneDlgState, 40); + } else { + for (int i = 0; i < 40; ++i) + _newSceneDlgState[i] = in.readUint16(); + } + for (int i = 0; i < 100; ++i) _hiddenItems[i] = in.readUint16(); - in.read(_scoreFlagTable, sizeof(_scoreFlagTable)); + + if (header.originalSave) + in.read(_flagsTable, 69); + in.read(_scoreFlagTable, 26); _mainCharacter.sceneId = in.readUint16(); _mainCharacter.dlgIndex = in.readSint16(); _mainCharacter.height = in.readByte(); _mainCharacter.facing = in.readByte(); _mainCharacter.animFrame = in.readUint16(); - _mainCharacter.walkspeed = in.readByte(); + if (!header.originalSave) { + _mainCharacter.walkspeed = in.readByte(); + } else { + in.seek(2, SEEK_CUR); + _mainCharacter.walkspeed = in.readUint32(); + } for (int i = 0; i < 10; ++i) _mainCharacter.inventory[i] = in.readUint16(); _mainCharacter.x1 = in.readSint16(); @@ -188,7 +219,7 @@ void KyraEngine_MR::loadGame(const char *fileName) { _itemList[i].sceneId = in.readUint16(); _itemList[i].x = in.readSint16(); _itemList[i].y = in.readSint16(); - if (header.version <= 9) + if (header.version <= 9 || header.originalSave) in.readUint16(); } @@ -199,11 +230,25 @@ void KyraEngine_MR::loadGame(const char *fileName) { _talkObjectList[i].x = in.readSint16(); _talkObjectList[i].y = in.readSint16(); _talkObjectList[i].color = in.readByte(); + if (header.version >= 13 || header.originalSave) + _talkObjectList[i].sceneId = in.readByte(); } for (int i = 0; i < 98; ++i) { - in.read(_sceneList[i].filename1, 10); - in.read(_sceneList[i].filename2, 10); + if (!header.originalSave) { + in.read(_sceneList[i].filename1, 10); + } else { + in.read(_sceneList[i].filename1, 9); + _sceneList[i].filename1[9] = 0; + } + + if (!header.originalSave) { + in.read(_sceneList[i].filename2, 10); + } else { + in.read(_sceneList[i].filename2, 9); + _sceneList[i].filename2[9] = 0; + } + _sceneList[i].exit1 = in.readUint16(); _sceneList[i].exit2 = in.readUint16(); _sceneList[i].exit3 = in.readUint16(); @@ -213,6 +258,26 @@ void KyraEngine_MR::loadGame(const char *fileName) { } _itemInHand = in.readSint16(); + + if (header.originalSave) { + uint32 currentTime = _system->getMillis(); + + for (int i = 0; i < 6; ++i) + _timer->setDelay(i, in.readSint32LE()); + + for (int i = 0; i < 6; ++i) { + if (in.readUint16LE()) + _timer->enable(i); + else + _timer->disable(i); + } + + for (int i = 0; i < 6; ++i) + _timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength)); + + _timer->resetNextRun(); + } + _sceneExit1 = in.readUint16(); _sceneExit2 = in.readUint16(); _sceneExit3 = in.readUint16(); diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp deleted file mode 100644 index f3e41b2d39..0000000000 --- a/engines/kyra/scene.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* 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 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 "kyra/kyra.h" -#include "kyra/screen.h" - -namespace Kyra { - -int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { - debugC(9, kDebugLevelMain, "KyraEngine::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); - x &= 0xFFFC; toX &= 0xFFFC; - y &= 0xFFFE; toY &= 0xFFFE; - x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY; - - if (x == toY && y == toY) { - moveTable[0] = 8; - return 0; - } - - int curX = x; - int curY = y; - int tempValue = 0; - int lastUsedEntry = 0; - int *pathTable1 = new int[0x7D0]; - int *pathTable2 = new int[0x7D0]; - assert(pathTable1 && pathTable2); - - while (true) { - int newFacing = getFacingFromPointToPoint(x, y, toX, toY); - changePosTowardsFacing(curX, curY, newFacing); - - if (curX == toX && curY == toY) { - if (!lineIsPassable(curX, curY)) - break; - moveTable[lastUsedEntry++] = newFacing; - break; - } - - if (lineIsPassable(curX, curY)) { - if (lastUsedEntry == moveTableSize) { - delete [] pathTable1; - delete [] pathTable2; - return 0x7D00; - } - // debug drawing - /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) { - screen()->setPagePixel(0, curX, curY, 11); - screen()->updateScreen(); - //waitTicks(5); - }*/ - moveTable[lastUsedEntry++] = newFacing; - x = curX; - y = curY; - continue; - } - - int temp = 0; - while (true) { - newFacing = getFacingFromPointToPoint(curX, curY, toX, toY); - changePosTowardsFacing(curX, curY, newFacing); - // debug drawing - /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) { - screen()->setPagePixel(0, curX, curY, 8); - screen()->updateScreen(); - //waitTicks(5); - }*/ - - if (!lineIsPassable(curX, curY)) { - if (curX != toX || curY != toY) - continue; - } - - if (curX == toX && curY == toY) { - if (!lineIsPassable(curX, curY)) { - tempValue = 0; - temp = 0; - break; - } - } - - temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0); - tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0); - if (curX == toX && curY == toY) { - if (temp == 0x7D00 && tempValue == 0x7D00) { - delete [] pathTable1; - delete [] pathTable2; - return 0x7D00; - } - } - - if (temp != 0x7D00 || tempValue != 0x7D00) - break; - } - - if (temp < tempValue) { - if (lastUsedEntry + temp > moveTableSize) { - delete [] pathTable1; - delete [] pathTable2; - return 0x7D00; - } - memcpy(&moveTable[lastUsedEntry], pathTable1, temp*sizeof(int)); - lastUsedEntry += temp; - } else { - if (lastUsedEntry + tempValue > moveTableSize) { - delete [] pathTable1; - delete [] pathTable2; - return 0x7D00; - } - memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue*sizeof(int)); - lastUsedEntry += tempValue; - } - x = curX; - y = curY; - if (curX == toX && curY == toY) - break; - } - - delete [] pathTable1; - delete [] pathTable2; - moveTable[lastUsedEntry] = 8; - return lastUsedEntry; -} - -int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) { - debugC(9, kDebugLevelMain, "KyraEngine::findSubPath(%d, %d, %d, %d, %p, %d, %d)", x, y, toX, toY, (const void *)moveTable, start, end); - // only used for debug specific code - //static uint16 unkTable[] = { 8, 5 }; - static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 }; - static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 }; - static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 }; - static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 }; - static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 }; - - // debug specific - /*++unkTable[start]; - while (screen()->getPalette(0)[unkTable[start]] != 0x0F) { - ++unkTable[start]; - }*/ - - int xpos1 = x, xpos2 = x; - int ypos1 = y, ypos2 = y; - int newFacing = getFacingFromPointToPoint(x, y, toX, toY); - int position = 0; - - while (position != end) { - int newFacing2 = newFacing; - while (true) { - changePosTowardsFacing(xpos1, ypos1, facingTable1[start*8 + newFacing2]); - if (!lineIsPassable(xpos1, ypos1)) { - if (facingTable1[start*8 + newFacing2] == newFacing) - return 0x7D00; - newFacing2 = facingTable1[start*8 + newFacing2]; - xpos1 = x; - ypos1 = y; - continue; - } - newFacing = facingTable1[start*8 + newFacing2]; - break; - } - // debug drawing - /*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) { - screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]); - screen()->updateScreen(); - //waitTicks(5); - }*/ - if (newFacing & 1) { - int temp = xpos1 + addPosTableX[newFacing + start * 8]; - if (toX == temp) { - temp = ypos1 + addPosTableY[newFacing + start * 8]; - if (toY == temp) { - moveTable[position++] = facingTable2[newFacing + start * 8]; - return position; - } - } - } - - moveTable[position++] = newFacing; - x = xpos1; - y = ypos1; - - if (x == toX && y == toY) - return position; - - if (xpos1 == xpos2 && ypos1 == ypos2) - break; - - newFacing = facingTable3[start*8 + newFacing]; - } - - return 0x7D00; -} - -int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) { - debugC(9, kDebugLevelMain, "KyraEngine::getFacingFromPointToPoint(%d, %d, %d, %d)", x, y, toX, toY); - static const int facingTable[] = { - 1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6 - }; - - int facingEntry = 0; - int ydiff = y - toY; - if (ydiff < 0) { - ++facingEntry; - ydiff = -ydiff; - } - facingEntry <<= 1; - - int xdiff = toX - x; - if (xdiff < 0) { - ++facingEntry; - xdiff = -xdiff; - } - - if (xdiff >= ydiff) { - int temp = ydiff; - ydiff = xdiff; - xdiff = temp; - - facingEntry <<= 1; - } else { - facingEntry <<= 1; - facingEntry += 1; - } - int temp = (ydiff + 1) >> 1; - - if (xdiff < temp) { - facingEntry <<= 1; - facingEntry += 1; - } else { - facingEntry <<= 1; - } - - assert(facingEntry < ARRAYSIZE(facingTable)); - return facingTable[facingEntry]; -} - - -int KyraEngine::getOppositeFacingDirection(int dir) { - debugC(9, kDebugLevelMain, "KyraEngine::getOppositeFacingDirection(%d)", dir); - switch (dir) { - case 0: - return 2; - case 1: - return 1; - case 3: - return 7; - case 4: - return 6; - case 5: - return 5; - case 6: - return 4; - case 7: - return 3; - default: - break; - } - return 0; -} - -void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) { - debugC(9, kDebugLevelMain, "KyraEngine::changePosTowardsFacing(%d, %d, %d)", x, y, facing); - x += _addXPosTable[facing]; - y += _addYPosTable[facing]; -} - -int KyraEngine::getMoveTableSize(int *moveTable) { - debugC(9, kDebugLevelMain, "KyraEngine::getMoveTableSize(%p)", (const void *)moveTable); - int retValue = 0; - if (moveTable[0] == 8) - return 0; - - static const int facingTable[] = { - 4, 5, 6, 7, 0, 1, 2, 3 - }; - static const int unkTable[] = { - -1, -1, 1, 2, -1, 6, 7, -1, - -1, -1, -1, -1, 2, -1, 0, -1, - 1, -1, -1, -1, 3, 4, -1, 0, - 2, -1, -1, -1, -1, -1, 4, -1, - -1, 2, 3, -1, -1, -1, 5, 6, - 6, -1, 4, -1, -1, -1, -1, -1, - 7, 0, -1, 4, 5, -1, -1, -1, - -1, -1, 0, -1, 6, -1, -1, -1 - }; - - int *oldPosition = moveTable; - int *tempPosition = moveTable; - int *curPosition = moveTable + 1; - retValue = 1; - - while (*curPosition != 8) { - if (*oldPosition == facingTable[*curPosition]) { - retValue -= 2; - *oldPosition = 9; - *curPosition = 9; - - while (tempPosition != moveTable) { - --tempPosition; - if (*tempPosition != 9) - break; - } - - if (tempPosition == moveTable && *tempPosition == 9) { - while (*tempPosition != 8 && *tempPosition == 9) - ++tempPosition; - - if (*tempPosition == 8) - return 0; - } - - oldPosition = tempPosition; - curPosition = oldPosition+1; - - while (*curPosition != 8 && *curPosition == 9) - ++curPosition; - - continue; - } - - if (unkTable[*curPosition+((*oldPosition)*8)] != -1) { - --retValue; - *oldPosition = unkTable[*curPosition+((*oldPosition)*8)]; - *curPosition = 9; - - if (tempPosition != oldPosition) { - curPosition = oldPosition; - oldPosition = tempPosition; - while (true) { - if (tempPosition == moveTable) - break; - - --tempPosition; - if (*tempPosition != 9) - break; - - } - } else { - while (true) { - ++curPosition; - if (*curPosition != 9) - break; - } - } - continue; - } - - tempPosition = oldPosition; - oldPosition = curPosition; - ++retValue; - - while (true) { - ++curPosition; - if (*curPosition != 9) - break; - } - } - - return retValue; -} - -} // end of namespace Kyra diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index 3fc7947253..1882386b03 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -98,7 +98,7 @@ void KyraEngine_HoF::enterNewScene(uint16 newScene, int facing, int unk1, int un _emc->run(&_sceneScriptState); } - Common::for_each(_wsaSlots, _wsaSlots+ARRAYSIZE(_wsaSlots), Common::mem_fun(&WSAMovieV2::close)); + Common::for_each(_wsaSlots, _wsaSlots+ARRAYSIZE(_wsaSlots), Common::mem_fun(&WSAMovie_v2::close)); _specialExitCount = 0; memset(_specialExitTable, -1, sizeof(_specialExitTable)); @@ -322,6 +322,8 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { refreshAnimObjectsIfNeed(); updateType = -1; } + + delay(10); } if (updateChar) @@ -702,7 +704,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) { void KyraEngine_HoF::freeSceneShapePtrs() { debugC(9, kDebugLevelMain, "KyraEngine_HoF::freeSceneShapePtrs()"); for (int i = 0; i < ARRAYSIZE(_sceneShapeTable); ++i) - delete [] _sceneShapeTable[i]; + delete[] _sceneShapeTable[i]; memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable)); } diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp new file mode 100644 index 0000000000..e4ae67f751 --- /dev/null +++ b/engines/kyra/scene_lok.cpp @@ -0,0 +1,1284 @@ +/* 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 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 "kyra/kyra_lok.h" +#include "kyra/seqplayer.h" +#include "kyra/screen.h" +#include "kyra/resource.h" +#include "kyra/sound.h" +#include "kyra/sprites.h" +#include "kyra/wsamovie.h" +#include "kyra/animator_lok.h" +#include "kyra/text.h" +#include "kyra/script.h" +#include "kyra/timer.h" + +#include "common/system.h" +#include "common/savefile.h" + +namespace Kyra { + +void KyraEngine_LoK::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive); + int unkVar1 = 1; + _screen->hideMouse(); + _handleInput = false; + _abortWalkFlag = false; + _abortWalkFlag2 = false; + + if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { + int newSfxFile = -1; + if (_currentCharacter->sceneId == 7 && sceneId == 24) + newSfxFile = 2; + else if (_currentCharacter->sceneId == 25 && sceneId == 109) + newSfxFile = 3; + else if (_currentCharacter->sceneId == 120 && sceneId == 37) + newSfxFile = 4; + else if (_currentCharacter->sceneId == 52 && sceneId == 199) + newSfxFile = 5; + else if (_currentCharacter->sceneId == 37 && sceneId == 120) + newSfxFile = 3; + else if (_currentCharacter->sceneId == 109 && sceneId == 25) + newSfxFile = 2; + else if (_currentCharacter->sceneId == 24 && sceneId == 7) + newSfxFile = 1; + + if (newSfxFile != -1) { + _curSfxFile = newSfxFile; + _sound->loadSoundFile(_curSfxFile); + } + } + + switch (_currentCharacter->sceneId) { + case 1: + if (sceneId == 0) { + moveCharacterToPos(0, 0, _currentCharacter->x1, 84); + unkVar1 = 0; + } + break; + + case 3: + if (sceneId == 2) { + moveCharacterToPos(0, 6, 155, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + case 26: + if (sceneId == 27) { + moveCharacterToPos(0, 6, 155, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + case 44: + if (sceneId == 45) { + moveCharacterToPos(0, 2, 192, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + default: + break; + } + + if (unkVar1 && unk1) { + int xpos = _currentCharacter->x1; + int ypos = _currentCharacter->y1; + switch (facing) { + case 0: + ypos = _currentCharacter->y1 - 6; + break; + + case 2: + xpos = 336; + break; + + case 4: + ypos = 143; + break; + + case 6: + xpos = -16; + break; + + default: + break; + } + + moveCharacterToPos(0, facing, xpos, ypos); + } + + for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) + _movieObjects[i]->close(); + + if (!brandonAlive) { + _emc->init(&_scriptClick, &_scriptClickData); + _emc->start(&_scriptClick, 5); + while (_emc->isValid(&_scriptClick)) + _emc->run(&_scriptClick); + } + + memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4); + _currentCharacter->sceneId = sceneId; + + assert(sceneId < _roomTableSize); + assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize); + + Room *currentRoom = &_roomTable[sceneId]; + + setupSceneResource(sceneId); + + _currentRoom = sceneId; + + int tableId = _roomTable[sceneId].nameIndex; + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".DAT"); + _sprites->loadDat(fileNameBuffer, _sceneExits); + _sprites->setupSceneAnims(); + _emc->unload(&_scriptClickData); + loadSceneMsc(); + + _walkBlockNorth = currentRoom->northExit; + _walkBlockEast = currentRoom->eastExit; + _walkBlockSouth = currentRoom->southExit; + _walkBlockWest = currentRoom->westExit; + + if (_walkBlockNorth == 0xFFFF) + _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3); + if (_walkBlockEast == 0xFFFF) + _screen->blockOutRegion(312, 0, 8, 139); + if (_walkBlockSouth == 0xFFFF) + _screen->blockOutRegion(0, 135, 320, 8); + if (_walkBlockWest == 0xFFFF) + _screen->blockOutRegion(0, 0, 8, 139); + + if (!brandonAlive) + updatePlayerItemsForScene(); + + startSceneScript(brandonAlive); + setupSceneItems(); + + initSceneData(facing, unk2, brandonAlive); + + _loopFlag2 = 0; + _screen->showMouse(); + if (!brandonAlive) + seq_poisonDeathNow(0); + updateMousePointer(true); + _changedScene = true; +} + +void KyraEngine_LoK::transcendScenes(int roomIndex, int roomName) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::transcendScenes(%d, %d)", roomIndex, roomName); + assert(roomIndex < _roomTableSize); + + if (_flags.isTalkie) { + char file[32]; + assert(roomIndex < _roomTableSize); + int tableId = _roomTable[roomIndex].nameIndex; + assert(tableId < _roomFilenameTableSize); + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".VRM"); + _res->unloadPakFile(file); + } + + _roomTable[roomIndex].nameIndex = roomName; + _unkScreenVar2 = 1; + _unkScreenVar3 = 1; + _unkScreenVar1 = 0; + _brandonPosX = _currentCharacter->x1; + _brandonPosY = _currentCharacter->y1; + enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0); + _unkScreenVar1 = 1; + _unkScreenVar2 = 0; + _unkScreenVar3 = 0; +} + +void KyraEngine_LoK::setSceneFile(int roomIndex, int roomName) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setSceneFile(%d, %d)", roomIndex, roomName); + assert(roomIndex < _roomTableSize); + _roomTable[roomIndex].nameIndex = roomName; +} + +void KyraEngine_LoK::moveCharacterToPos(int character, int facing, int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos); + Character *ch = &_characterList[character]; + ch->facing = facing; + _screen->hideMouse(); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); + _timer->disable(19); + _timer->disable(14); + _timer->disable(18); + uint32 nextFrame = 0; + + switch (facing) { + case 0: + while (ypos < ch->y1) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + case 2: + while (ch->x1 < xpos) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + case 4: + while (ypos > ch->y1) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + case 6: + while (ch->x1 > xpos) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + default: + break; + } + + _timer->enable(19); + _timer->enable(14); + _timer->enable(18); + _screen->showMouse(); +} + +void KyraEngine_LoK::setCharacterPositionWithUpdate(int character) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setCharacterPositionWithUpdate(%d)", character); + setCharacterPosition(character, 0); + _sprites->updateSceneAnims(); + _timer->update(); + _animator->updateAllObjectShapes(); + updateTextFade(); + + if (_currentCharacter->sceneId == 210) + updateKyragemFading(); +} + +int KyraEngine_LoK::setCharacterPosition(int character, int *facingTable) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setCharacterPosition(%d, %p)", character, (const void *)facingTable); + + if (character == 0) { + _currentCharacter->x1 += _charAddXPosTable[_currentCharacter->facing]; + _currentCharacter->y1 += _charAddYPosTable[_currentCharacter->facing]; + setCharacterPositionHelper(0, facingTable); + return 1; + } else { + _characterList[character].x1 += _charAddXPosTable[_characterList[character].facing]; + _characterList[character].y1 += _charAddYPosTable[_characterList[character].facing]; + if (_characterList[character].sceneId == _currentCharacter->sceneId) + setCharacterPositionHelper(character, 0); + } + return 0; +} + +void KyraEngine_LoK::setCharacterPositionHelper(int character, int *facingTable) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setCharacterPositionHelper(%d, %p)", character, (const void *)facingTable); + Character *ch = &_characterList[character]; + ++ch->currentAnimFrame; + int facing = ch->facing; + if (facingTable) { + if (*facingTable != *(facingTable - 1)) { + if (*(facingTable - 1) == *(facingTable + 1)) { + facing = getOppositeFacingDirection(*(facingTable - 1)); + *facingTable = *(facingTable - 1); + } + } + } + + static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + if (facing == 0) { + ++facingIsZero[character]; + } else { + bool resetTables = false; + if (facing != 7) { + if (facing - 1 != 0) { + if (facing != 4) { + if (facing == 3 || facing == 5) { + if (facingIsFour[character] > 2) + facing = 4; + resetTables = true; + } + } else { + ++facingIsFour[character]; + } + } else { + if (facingIsZero[character] > 2) + facing = 0; + resetTables = true; + } + } else { + if (facingIsZero[character] > 2) + facing = 0; + resetTables = true; + } + + if (resetTables) { + facingIsZero[character] = 0; + facingIsFour[character] = 0; + } + } + + static const uint16 maxAnimationFrame[] = { + 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000, + 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000, + 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000, + 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000, + 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000, + 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000, + 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000 + }; + + if (facing == 0) { + if (maxAnimationFrame[36+character] > ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[36+character]; + if (maxAnimationFrame[30+character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[36+character]; + } else if (facing == 4) { + if (maxAnimationFrame[18+character] > ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[18+character]; + if (maxAnimationFrame[12+character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[18+character]; + } else { + if (maxAnimationFrame[18+character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[30+character]; + if (maxAnimationFrame[character] == ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[6+character]; + if (maxAnimationFrame[character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[6+character]+2; + } + + if (character == 0 && (_brandonStatusBit & 0x10)) + ch->currentAnimFrame = 88; + + _animator->animRefreshNPC(character); +} + +void KyraEngine_LoK::loadSceneMsc() { + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".MSC"); + _screen->fillRect(0, 0, 319, 199, 0, 5); + _res->exists(fileNameBuffer, true); + _screen->loadBitmap(fileNameBuffer, 3, 5, 0); +} + +void KyraEngine_LoK::startSceneScript(int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::startSceneScript(%d)", brandonAlive); + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".CPS"); + _screen->clearPage(3); + _res->exists(fileNameBuffer, true); + // FIXME: check this hack for amiga version + _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0)); + _sprites->loadSceneShapes(); + _exitListPtr = 0; + + _scaleMode = 1; + for (int i = 0; i < 145; ++i) + _scaleTable[i] = 256; + + clearNoDropRects(); + _emc->init(&_scriptClick, &_scriptClickData); + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".EMC"); + _res->exists(fileNameBuffer, true); + _emc->unload(&_scriptClickData); + _emc->load(fileNameBuffer, &_scriptClickData, &_opcodes); + _emc->start(&_scriptClick, 0); + _scriptClick.regs[0] = _currentCharacter->sceneId; + _scriptClick.regs[7] = brandonAlive; + + while (_emc->isValid(&_scriptClick)) + _emc->run(&_scriptClick); +} + +void KyraEngine_LoK::initSceneData(int facing, int unk1, int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive); + + int16 xpos2 = 0; + int setFacing = 1; + + int16 xpos = 0, ypos = 0; + + if (_brandonPosX == -1 && _brandonPosY == -1) { + switch (facing + 1) { + case 0: + xpos = ypos = -1; + break; + + case 1: case 2: case 8: + xpos = _sceneExits.southXPos; + ypos = _sceneExits.southYPos; + break; + + case 3: + xpos = _sceneExits.westXPos; + ypos = _sceneExits.westYPos; + break; + + case 4: case 5: case 6: + xpos = _sceneExits.northXPos; + ypos = _sceneExits.northYPos; + break; + + case 7: + xpos = _sceneExits.eastXPos; + ypos = _sceneExits.eastYPos; + break; + + default: + break; + } + + if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) + ypos = (_northExitHeight & 0xFF) + 4; + if (xpos >= 308) + xpos = 304; + if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) + ypos = (_northExitHeight >> 8) - 4; + if (xpos <= 12) + xpos = 16; + } + + if (_brandonPosX > -1) + xpos = _brandonPosX; + if (_brandonPosY > -1) + ypos = _brandonPosY; + + int16 ypos2 = 0; + if (_brandonPosX > -1 && _brandonPosY > -1) { + switch (_currentCharacter->sceneId) { + case 1: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 4; + xpos2 = 192; + ypos2 = 104; + setFacing = 0; + unk1 = 1; + break; + + case 3: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 204; + ypos2 = 94; + setFacing = 0; + unk1 = 1; + break; + + case 26: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 192; + ypos2 = 128; + setFacing = 0; + unk1 = 1; + break; + + case 44: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 6; + xpos2 = 156; + ypos2 = 96; + setFacing = 0; + unk1 = 1; + break; + + case 37: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 148; + ypos2 = 114; + setFacing = 0; + unk1 = 1; + break; + + default: + break; + } + } + + _brandonPosX = _brandonPosY = -1; + + if (unk1 && setFacing) { + ypos2 = ypos; + xpos2 = xpos; + switch (facing) { + case 0: + ypos = 142; + break; + + case 2: + xpos = -16; + break; + + case 4: + ypos = (uint8)(_northExitHeight & 0xFF) - 4; + break; + + case 6: + xpos = 336; + break; + + default: + break; + } + } + + xpos2 = (int16)(xpos2 & 0xFFFC); + ypos2 = (int16)(ypos2 & 0xFFFE); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); + _currentCharacter->facing = facing; + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + + initSceneObjectList(brandonAlive); + + if (unk1 && brandonAlive == 0) + moveCharacterToPos(0, facing, xpos2, ypos2); + + _scriptClick.regs[4] = _itemInHand; + _scriptClick.regs[7] = brandonAlive; + _emc->start(&_scriptClick, 3); + while (_emc->isValid(&_scriptClick)) + _emc->run(&_scriptClick); +} + +void KyraEngine_LoK::initSceneObjectList(int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::initSceneObjectList(%d)", brandonAlive); + for (int i = 0; i < 28; ++i) + _animator->actors()[i].active = 0; + + int startAnimFrame = 0; + + Animator_LoK::AnimObject *curAnimState = _animator->actors(); + curAnimState->active = 1; + curAnimState->drawY = _currentCharacter->y1; + curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame]; + curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame; + startAnimFrame = _currentCharacter->currentAnimFrame-7; + int xOffset = _defaultShapeTable[startAnimFrame].xOffset; + int yOffset = _defaultShapeTable[startAnimFrame].yOffset; + + if (_scaleMode) { + curAnimState->x1 = _currentCharacter->x1; + curAnimState->y1 = _currentCharacter->y1; + + _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1]; + _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1]; + + curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; + curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; + } else { + curAnimState->x1 = _currentCharacter->x1 + xOffset; + curAnimState->y1 = _currentCharacter->y1 + yOffset; + } + + curAnimState->x2 = curAnimState->x1; + curAnimState->y2 = curAnimState->y1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + _animator->clearQueue(); + _animator->addObjectToQueue(curAnimState); + + int listAdded = 0; + int addedObjects = 1; + + for (int i = 1; i < 5; ++i) { + Character *ch = &_characterList[i]; + curAnimState = &_animator->actors()[addedObjects]; + if (ch->sceneId != _currentCharacter->sceneId) { + curAnimState->active = 0; + curAnimState->refreshFlag = 0; + curAnimState->bkgdChangeFlag = 0; + ++addedObjects; + continue; + } + + curAnimState->drawY = ch->y1; + curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame]; + curAnimState->animFrameNumber = ch->currentAnimFrame; + startAnimFrame = ch->currentAnimFrame-7; + xOffset = _defaultShapeTable[startAnimFrame].xOffset; + yOffset = _defaultShapeTable[startAnimFrame].yOffset; + if (_scaleMode) { + curAnimState->x1 = ch->x1; + curAnimState->y1 = ch->y1; + + _animator->_brandonScaleX = _scaleTable[ch->y1]; + _animator->_brandonScaleY = _scaleTable[ch->y1]; + + curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; + curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; + } else { + curAnimState->x1 = ch->x1 + xOffset; + curAnimState->y1 = ch->y1 + yOffset; + } + curAnimState->x2 = curAnimState->x1; + curAnimState->y2 = curAnimState->y1; + curAnimState->active = 1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + + if (ch->facing >= 1 && ch->facing <= 3) + curAnimState->flags |= 1; + else if (ch->facing >= 5 && ch->facing <= 7) + curAnimState->flags &= 0xFFFFFFFE; + + _animator->addObjectToQueue(curAnimState); + + ++addedObjects; + ++listAdded; + if (listAdded < 2) + i = 5; + } + + for (int i = 0; i < 11; ++i) { + curAnimState = &_animator->sprites()[i]; + + if (_sprites->_anims[i].play) { + curAnimState->active = 1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + } else { + curAnimState->active = 0; + curAnimState->refreshFlag = 0; + curAnimState->bkgdChangeFlag = 0; + } + curAnimState->height = _sprites->_anims[i].height; + curAnimState->height2 = _sprites->_anims[i].height2; + curAnimState->width = _sprites->_anims[i].width + 1; + curAnimState->width2 = _sprites->_anims[i].width2; + curAnimState->drawY = _sprites->_anims[i].drawY; + curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x; + curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y; + curAnimState->background = _sprites->_anims[i].background; + curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite]; + + curAnimState->disable = _sprites->_anims[i].disable; + + if (_sprites->_anims[i].unk2) + curAnimState->flags = 0x800; + else + curAnimState->flags = 0; + + if (_sprites->_anims[i].flipX) + curAnimState->flags |= 0x1; + + _animator->addObjectToQueue(curAnimState); + } + + for (int i = 0; i < 12; ++i) { + curAnimState = &_animator->items()[i]; + Room *curRoom = &_roomTable[_currentCharacter->sceneId]; + byte curItem = curRoom->itemsTable[i]; + if (curItem != 0xFF) { + curAnimState->drawY = curRoom->itemsYPos[i]; + curAnimState->sceneAnimPtr = _shapes[216+curItem]; + curAnimState->animFrameNumber = (int16)0xFFFF; + curAnimState->y1 = curRoom->itemsYPos[i]; + curAnimState->x1 = curRoom->itemsXPos[i]; + + curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1; + curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]); + + curAnimState->x2 = curAnimState->x1; + curAnimState->y2 = curAnimState->y1; + + curAnimState->active = 1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + + _animator->addObjectToQueue(curAnimState); + } else { + curAnimState->active = 0; + curAnimState->refreshFlag = 0; + curAnimState->bkgdChangeFlag = 0; + } + } + + _animator->preserveAnyChangedBackgrounds(); + curAnimState = _animator->actors(); + curAnimState->bkgdChangeFlag = 1; + curAnimState->refreshFlag = 1; + for (int i = 1; i < 28; ++i) { + curAnimState = &_animator->objects()[i]; + if (curAnimState->active) { + curAnimState->bkgdChangeFlag = 1; + curAnimState->refreshFlag = 1; + } + } + _animator->restoreAllObjectBackgrounds(); + _animator->preserveAnyChangedBackgrounds(); + _animator->prepDrawAllObjects(); + initSceneScreen(brandonAlive); + _animator->copyChangedObjectsForward(0); +} + +void KyraEngine_LoK::initSceneScreen(int brandonAlive) { + if (_flags.platform == Common::kPlatformAmiga) { + if (_unkScreenVar1 && !queryGameFlag(0xF0)) { + memset(_screen->getPalette(2), 0, 32*3); + if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3)) + _screen->setScreenPalette(_screen->getPalette(2)); + } + + if (_unkScreenVar2 == 1) + _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); + else + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + + if (_unkScreenVar1 && !queryGameFlag(0xA0)) { + if (_currentCharacter->sceneId == 45 && _paletteChanged) + memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2); + + if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) + memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64); + + _screen->setScreenPalette(_screen->getPalette(0)); + } + } else { + if (_unkScreenVar1 && !queryGameFlag(0xA0)) { + for (int i = 0; i < 60; ++i) { + uint16 col = _screen->getPalette(0)[684+i]; + col += _screen->getPalette(1)[684+i] << 1; + col >>= 2; + _screen->getPalette(0)[684+i] = col; + } + _screen->setScreenPalette(_screen->getPalette(0)); + } + + if (_unkScreenVar2 == 1) + _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); + else + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + + if (_unkScreenVar1 && _paletteChanged) { + if (!queryGameFlag(0xA0)) { + memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60); + _screen->setScreenPalette(_screen->getPalette(0)); + } else { + memset(_screen->getPalette(0), 0, 768); + } + } + } + + if (!_emc->start(&_scriptClick, 2)) + error("Could not start script function 2 of scene script"); + + _scriptClick.regs[7] = brandonAlive; + + while (_emc->isValid(&_scriptClick)) + _emc->run(&_scriptClick); + + setTextFadeTimerCountdown(-1); + if (_currentCharacter->sceneId == 210) { + if (_itemInHand != -1) + magicOutMouseItem(2, -1); + + _screen->hideMouse(); + for (int i = 0; i < 10; ++i) { + if (_currentCharacter->inventoryItems[i] != 0xFF) + magicOutMouseItem(2, i); + } + _screen->showMouse(); + } +} + +int KyraEngine_LoK::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset); + if (queryGameFlag(0xEF)) + unk1 = 0; + + int sceneId = _currentCharacter->sceneId; + _pathfinderFlag = 0; + + if (xpos < 12) { + if (_roomTable[sceneId].westExit != 0xFFFF) { + xpos = 12; + ypos = _sceneExits.westYPos; + _pathfinderFlag = 7; + } + } else if (xpos >= 308) { + if (_roomTable[sceneId].eastExit != 0xFFFF) { + xpos = 307; + ypos = _sceneExits.eastYPos; + _pathfinderFlag = 13; + } + } + + if (ypos <= (_northExitHeight&0xFF)+2) { + if (_roomTable[sceneId].northExit != 0xFFFF) { + xpos = _sceneExits.northXPos; + ypos = _northExitHeight & 0xFF; + _pathfinderFlag = 14; + } + } else if (ypos >= 136) { + if (_roomTable[sceneId].southExit != 0xFFFF) { + xpos = _sceneExits.southXPos; + ypos = 136; + _pathfinderFlag = 11; + } + } + + int temp = xpos - _currentCharacter->x1; + if (ABS(temp) < 4) { + temp = ypos - _currentCharacter->y1; + if (ABS(temp) < 2) + return 0; + } + + int x = (int16)(_currentCharacter->x1 & 0xFFFC); + int y = (int16)(_currentCharacter->y1 & 0xFFFE); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); + + int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150); + _pathfinderFlag = 0; + + if (ret >= _lastFindWayRet) + _lastFindWayRet = ret; + + if (ret == 0x7D00 || ret == 0) + return 0; + + return processSceneChange(_movFacingTable, unk1, frameReset); +} + +int KyraEngine_LoK::processSceneChange(int *table, int unk1, int frameReset) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::processSceneChange(%p, %d, %d)", (const void *)table, unk1, frameReset); + if (queryGameFlag(0xEF)) + unk1 = 0; + + int *tableStart = table; + _sceneChangeState = 0; + _loopFlag2 = 0; + bool running = true; + int returnValue = 0; + uint32 nextFrame = 0; + _abortWalkFlag = false; + _mousePressFlag = false; + + while (running) { + if (_abortWalkFlag) { + *table = 8; + _currentCharacter->currentAnimFrame = 7; + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + processInput(); + return 0; + } + bool forceContinue = false; + switch (*table) { + case 0: case 1: case 2: + case 3: case 4: case 5: + case 6: case 7: + _currentCharacter->facing = getOppositeFacingDirection(*table); + break; + + case 8: + forceContinue = true; + running = false; + break; + + default: + ++table; + forceContinue = true; + break; + } + + returnValue = changeScene(_currentCharacter->facing); + if (returnValue) { + running = false; + _abortWalkFlag = false; + } + + if (unk1) { + if (_mousePressFlag) { + running = false; + _sceneChangeState = 1; + } + } + + if (forceContinue || !running) + continue; + + int temp = 0; + if (table == tableStart || table[1] == 8) + temp = setCharacterPosition(0, 0); + else + temp = setCharacterPosition(0, table); + + if (temp) + ++table; + + nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis(); + while (_system->getMillis() < nextFrame) { + _timer->update(); + + if (_currentCharacter->sceneId == 210) { + updateKyragemFading(); + if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) { + *table = 8; + running = false; + break; + } + } + + if ((nextFrame - _system->getMillis()) >= 10) + delay(10, true); + } + } + + if (frameReset && !(_brandonStatusBit & 2)) + _currentCharacter->currentAnimFrame = 7; + + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + return returnValue; +} + +int KyraEngine_LoK::changeScene(int facing) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::changeScene(%d)", facing); + if (queryGameFlag(0xEF)) { + if (_currentCharacter->sceneId == 5) + return 0; + } + + int xpos = _charAddXPosTable[facing] + _currentCharacter->x1; + int ypos = _charAddYPosTable[facing] + _currentCharacter->y1; + + if (xpos >= 12 && xpos <= 308) { + if (!lineIsPassable(xpos, ypos)) + return false; + } + + if (_exitListPtr) { + int16 *ptr = _exitListPtr; + // this loop should be only entered one time, seems to be some hack in the original + while (true) { + if (*ptr == -1) + break; + + if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) { + ptr += 10; + break; + } + + _brandonPosX = ptr[6]; + _brandonPosY = ptr[7]; + uint16 sceneId = ptr[5]; + facing = ptr[4]; + int unk1 = ptr[8]; + int unk2 = ptr[9]; + + if (sceneId == 0xFFFF) { + switch (facing) { + case 0: + sceneId = _roomTable[_currentCharacter->sceneId].northExit; + break; + + case 2: + sceneId = _roomTable[_currentCharacter->sceneId].eastExit; + break; + + case 4: + sceneId = _roomTable[_currentCharacter->sceneId].southExit; + break; + + case 6: + sceneId = _roomTable[_currentCharacter->sceneId].westExit; + break; + + default: + break; + } + } + + _currentCharacter->facing = facing; + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + enterNewScene(sceneId, facing, unk1, unk2, 0); + resetGameFlag(0xEE); + return 1; + } + } + + int returnValue = 0; + facing = 0; + + if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) { + facing = 0; + returnValue = 1; + } + + if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) { + facing = 2; + returnValue = 1; + } + + if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) { + facing = 4; + returnValue = 1; + } + + if (xpos <= 12 || _currentCharacter->y1 <= 12) { + facing = 6; + returnValue = 1; + } + + if (!returnValue) + return 0; + + uint16 sceneId = 0xFFFF; + switch (facing) { + case 0: + sceneId = _roomTable[_currentCharacter->sceneId].northExit; + break; + + case 2: + sceneId = _roomTable[_currentCharacter->sceneId].eastExit; + break; + + case 4: + sceneId = _roomTable[_currentCharacter->sceneId].southExit; + break; + + default: + sceneId = _roomTable[_currentCharacter->sceneId].westExit; + break; + } + + if (sceneId == 0xFFFF) + return 0; + + enterNewScene(sceneId, facing, 1, 1, 0); + return returnValue; +} + +void KyraEngine_LoK::setCharactersInDefaultScene() { + static const uint32 defaultSceneTable[][4] = { + { 0xFFFF, 0x0004, 0x0003, 0xFFFF }, + { 0xFFFF, 0x0022, 0xFFFF, 0x0000 }, + { 0xFFFF, 0x001D, 0x0021, 0xFFFF }, + { 0xFFFF, 0x0000, 0x0000, 0xFFFF } + }; + + for (int i = 1; i < 5; ++i) { + Character *cur = &_characterList[i]; + //cur->field_20 = 0; + + const uint32 *curTable = defaultSceneTable[i-1]; + cur->sceneId = curTable[0]; + + if (cur->sceneId == _currentCharacter->sceneId) + //++cur->field_20; + cur->sceneId = curTable[1/*cur->field_20*/]; + + //cur->field_23 = curTable[cur->field_20+1]; + } +} + +void KyraEngine_LoK::setCharactersPositions(int character) { + static uint16 initXPosTable[] = { + 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B, + 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042 + }; + static uint8 initYPosTable[] = { + 0x00, 0xA2, 0x00, 0x42, 0x00, + 0x67, 0x67, 0x60, 0x5A, 0x71, + 0x76 + }; + + assert(character < ARRAYSIZE(initXPosTable)); + Character *edit = &_characterList[character]; + edit->x1 = edit->x2 = initXPosTable[character]; + edit->y1 = edit->y2 = initYPosTable[character]; +} + +#pragma mark - +#pragma mark - Pathfinder +#pragma mark - + +int KyraEngine_LoK::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); + int ret = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize); + if (ret == 0x7D00) + return 0; + return getMoveTableSize(moveTable); +} + +bool KyraEngine_LoK::lineIsPassable(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::lineIsPassable(%d, %d)", x, y); + if (queryGameFlag(0xEF)) { + if (_currentCharacter->sceneId == 5) + return true; + } + + if (_pathfinderFlag & 2) { + if (x >= 312) + return false; + } + + if (_pathfinderFlag & 4) { + if (y >= 136) + return false; + } + + if (_pathfinderFlag & 8) { + if (x < 8) + return false; + } + + if (_pathfinderFlag2) { + if (x <= 8 || x >= 312) + return true; + if (y < (_northExitHeight & 0xFF) || y > 135) + return true; + } + + if (y > 137) + return false; + + if (y < 0) + y = 0; + + int ypos = 8; + if (_scaleMode) { + ypos = (_scaleTable[y] >> 5) + 1; + if (8 < ypos) + ypos = 8; + } + + x -= (ypos >> 1); + + int xpos = x; + int xtemp = xpos + ypos - 1; + if (x < 0) + xpos = 0; + + if (xtemp > 319) + xtemp = 319; + + for (; xpos < xtemp; ++xpos) { + if (!_screen->getShapeFlag1(xpos, y)) + return false; + } + return true; +} + +#pragma mark - + +void KyraEngine_LoK::setupSceneResource(int sceneId) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setupSceneResource(%d)", sceneId); + if (!_flags.isTalkie) + return; + + if (_currentRoom != 0xFFFF) { + assert(_currentRoom < _roomTableSize); + int tableId = _roomTable[_currentRoom].nameIndex; + assert(tableId < _roomFilenameTableSize); + + // unload our old room + char file[64]; + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".VRM"); + _res->unloadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".PAK"); + _res->unloadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".APK"); + _res->unloadPakFile(file); + } + + assert(sceneId < _roomTableSize); + int tableId = _roomTable[sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + + // load our new room + char file[64]; + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".VRM"); + if (_res->exists(file)) + _res->loadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".PAK"); + if (_res->exists(file)) + _res->loadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".APK"); + if (_res->exists(file)) + _res->loadPakFile(file); +} + +} // end of namespace Kyra + diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index 196c87424d..e4a3a5c54e 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -182,7 +182,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 if (_itemInHand < 0) { _itemInHand = -1; - _handItemSet = -1; + _mouseState = -1; _screen->setMouseCursor(0, 0, _gameShapes[0]); } @@ -311,7 +311,7 @@ void KyraEngine_MR::enterNewSceneUnk2(int unk1) { void KyraEngine_MR::unloadScene() { debugC(9, kDebugLevelMain, "KyraEngine_MR::unloadScene()"); - delete [] _sceneStrings; + delete[] _sceneStrings; _sceneStrings = 0; musicUpdate(0); _emc->unload(&_sceneScriptData); @@ -325,7 +325,7 @@ void KyraEngine_MR::unloadScene() { void KyraEngine_MR::freeSceneShapes() { debugC(9, kDebugLevelMain, "KyraEngine_MR::freeSceneShapes()"); for (uint i = 0; i < ARRAYSIZE(_sceneShapes); ++i) { - delete [] _sceneShapes[i]; + delete[] _sceneShapes[i]; _sceneShapes[i] = 0; } } @@ -430,6 +430,8 @@ void KyraEngine_MR::initSceneScript(int unk1) { _screen->_curPage = pageBackUp; musicUpdate(0); } + delete stream; + stream = 0; musicUpdate(0); strcpy(filename, scene.filename1); @@ -691,7 +693,7 @@ int KyraEngine_MR::trySceneChange(int *moveTable, int unk1, int updateChar) { if (ret) ++moveTable; - update(); + delay(10, true); } if (updateChar) diff --git a/engines/kyra/scene_v1.cpp b/engines/kyra/scene_v1.cpp index c5d1de82a9..65171ad831 100644 --- a/engines/kyra/scene_v1.cpp +++ b/engines/kyra/scene_v1.cpp @@ -24,1261 +24,360 @@ */ #include "kyra/kyra_v1.h" -#include "kyra/seqplayer.h" #include "kyra/screen.h" -#include "kyra/resource.h" -#include "kyra/sound.h" -#include "kyra/sprites.h" -#include "kyra/wsamovie.h" -#include "kyra/animator_v1.h" -#include "kyra/text.h" -#include "kyra/script.h" -#include "kyra/timer.h" - -#include "common/system.h" -#include "common/savefile.h" namespace Kyra { -void KyraEngine_v1::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive); - int unkVar1 = 1; - _screen->hideMouse(); - _handleInput = false; - _abortWalkFlag = false; - _abortWalkFlag2 = false; - - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { - int newSfxFile = -1; - if (_currentCharacter->sceneId == 7 && sceneId == 24) - newSfxFile = 2; - else if (_currentCharacter->sceneId == 25 && sceneId == 109) - newSfxFile = 3; - else if (_currentCharacter->sceneId == 120 && sceneId == 37) - newSfxFile = 4; - else if (_currentCharacter->sceneId == 52 && sceneId == 199) - newSfxFile = 5; - else if (_currentCharacter->sceneId == 37 && sceneId == 120) - newSfxFile = 3; - else if (_currentCharacter->sceneId == 109 && sceneId == 25) - newSfxFile = 2; - else if (_currentCharacter->sceneId == 24 && sceneId == 7) - newSfxFile = 1; - - if (newSfxFile != -1) { - _curSfxFile = newSfxFile; - _sound->loadSoundFile(_curSfxFile); - } - } - - switch (_currentCharacter->sceneId) { - case 1: - if (sceneId == 0) { - moveCharacterToPos(0, 0, _currentCharacter->x1, 84); - unkVar1 = 0; - } - break; - - case 3: - if (sceneId == 2) { - moveCharacterToPos(0, 6, 155, _currentCharacter->y1); - unkVar1 = 0; - } - break; - - case 26: - if (sceneId == 27) { - moveCharacterToPos(0, 6, 155, _currentCharacter->y1); - unkVar1 = 0; - } - break; - - case 44: - if (sceneId == 45) { - moveCharacterToPos(0, 2, 192, _currentCharacter->y1); - unkVar1 = 0; - } - break; +int KyraEngine_v1::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); + x &= 0xFFFC; toX &= 0xFFFC; + y &= 0xFFFE; toY &= 0xFFFE; + x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY; - default: - break; + if (x == toY && y == toY) { + moveTable[0] = 8; + return 0; } - if (unkVar1 && unk1) { - int xpos = _currentCharacter->x1; - int ypos = _currentCharacter->y1; - switch (facing) { - case 0: - ypos = _currentCharacter->y1 - 6; - break; - - case 2: - xpos = 336; - break; - - case 4: - ypos = 143; - break; + int curX = x; + int curY = y; + int tempValue = 0; + int lastUsedEntry = 0; + int *pathTable1 = new int[0x7D0]; + int *pathTable2 = new int[0x7D0]; + assert(pathTable1 && pathTable2); - case 6: - xpos = -16; - break; + while (true) { + int newFacing = getFacingFromPointToPoint(x, y, toX, toY); + changePosTowardsFacing(curX, curY, newFacing); - default: + if (curX == toX && curY == toY) { + if (!lineIsPassable(curX, curY)) + break; + moveTable[lastUsedEntry++] = newFacing; break; } - moveCharacterToPos(0, facing, xpos, ypos); - } - - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) - _movieObjects[i]->close(); - - if (!brandonAlive) { - _emc->init(&_scriptClick, &_scriptClickData); - _emc->start(&_scriptClick, 5); - while (_emc->isValid(&_scriptClick)) - _emc->run(&_scriptClick); - } - - memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4); - _currentCharacter->sceneId = sceneId; - - assert(sceneId < _roomTableSize); - assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize); - - Room *currentRoom = &_roomTable[sceneId]; - - setupSceneResource(sceneId); - - _currentRoom = sceneId; - - int tableId = _roomTable[sceneId].nameIndex; - char fileNameBuffer[32]; - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".DAT"); - _sprites->loadDat(fileNameBuffer, _sceneExits); - _sprites->setupSceneAnims(); - _emc->unload(&_scriptClickData); - loadSceneMsc(); - - _walkBlockNorth = currentRoom->northExit; - _walkBlockEast = currentRoom->eastExit; - _walkBlockSouth = currentRoom->southExit; - _walkBlockWest = currentRoom->westExit; - - if (_walkBlockNorth == 0xFFFF) - _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3); - if (_walkBlockEast == 0xFFFF) - _screen->blockOutRegion(312, 0, 8, 139); - if (_walkBlockSouth == 0xFFFF) - _screen->blockOutRegion(0, 135, 320, 8); - if (_walkBlockWest == 0xFFFF) - _screen->blockOutRegion(0, 0, 8, 139); - - if (!brandonAlive) - updatePlayerItemsForScene(); - - startSceneScript(brandonAlive); - setupSceneItems(); - - initSceneData(facing, unk2, brandonAlive); - - _loopFlag2 = 0; - _screen->showMouse(); - if (!brandonAlive) - seq_poisonDeathNow(0); - updateMousePointer(true); - _changedScene = true; -} - -void KyraEngine_v1::transcendScenes(int roomIndex, int roomName) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::transcendScenes(%d, %d)", roomIndex, roomName); - assert(roomIndex < _roomTableSize); - - if (_flags.isTalkie) { - char file[32]; - assert(roomIndex < _roomTableSize); - int tableId = _roomTable[roomIndex].nameIndex; - assert(tableId < _roomFilenameTableSize); - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".VRM"); - _res->unloadPakFile(file); - } - - _roomTable[roomIndex].nameIndex = roomName; - _unkScreenVar2 = 1; - _unkScreenVar3 = 1; - _unkScreenVar1 = 0; - _brandonPosX = _currentCharacter->x1; - _brandonPosY = _currentCharacter->y1; - enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0); - _unkScreenVar1 = 1; - _unkScreenVar2 = 0; - _unkScreenVar3 = 0; -} - -void KyraEngine_v1::setSceneFile(int roomIndex, int roomName) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setSceneFile(%d, %d)", roomIndex, roomName); - assert(roomIndex < _roomTableSize); - _roomTable[roomIndex].nameIndex = roomName; -} - -void KyraEngine_v1::moveCharacterToPos(int character, int facing, int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos); - Character *ch = &_characterList[character]; - ch->facing = facing; - _screen->hideMouse(); - xpos = (int16)(xpos & 0xFFFC); - ypos = (int16)(ypos & 0xFFFE); - _timer->disable(19); - _timer->disable(14); - _timer->disable(18); - uint32 nextFrame = 0; - - switch (facing) { - case 0: - while (ypos < ch->y1) { - nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - case 2: - while (ch->x1 < xpos) { - nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - case 4: - while (ypos > ch->y1) { - nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - case 6: - while (ch->x1 > xpos) { - nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - default: - break; - } - - _timer->enable(19); - _timer->enable(14); - _timer->enable(18); - _screen->showMouse(); -} - -void KyraEngine_v1::setCharacterPositionWithUpdate(int character) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPositionWithUpdate(%d)", character); - setCharacterPosition(character, 0); - _sprites->updateSceneAnims(); - _timer->update(); - _animator->updateAllObjectShapes(); - updateTextFade(); - - if (_currentCharacter->sceneId == 210) - updateKyragemFading(); -} - -int KyraEngine_v1::setCharacterPosition(int character, int *facingTable) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPosition(%d, %p)", character, (const void *)facingTable); - - if (character == 0) { - _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing]; - _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing]; - setCharacterPositionHelper(0, facingTable); - return 1; - } else { - _characterList[character].x1 += _charXPosTable[_characterList[character].facing]; - _characterList[character].y1 += _charYPosTable[_characterList[character].facing]; - if (_characterList[character].sceneId == _currentCharacter->sceneId) - setCharacterPositionHelper(character, 0); - } - return 0; -} - -void KyraEngine_v1::setCharacterPositionHelper(int character, int *facingTable) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPositionHelper(%d, %p)", character, (const void *)facingTable); - Character *ch = &_characterList[character]; - ++ch->currentAnimFrame; - int facing = ch->facing; - if (facingTable) { - if (*facingTable != *(facingTable - 1)) { - if (*(facingTable - 1) == *(facingTable + 1)) { - facing = getOppositeFacingDirection(*(facingTable - 1)); - *facingTable = *(facingTable - 1); + if (lineIsPassable(curX, curY)) { + if (lastUsedEntry == moveTableSize) { + delete[] pathTable1; + delete[] pathTable2; + return 0x7D00; } + // debug drawing + /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) { + screen()->setPagePixel(0, curX, curY, 11); + screen()->updateScreen(); + delayWithTicks(5); + }*/ + moveTable[lastUsedEntry++] = newFacing; + x = curX; + y = curY; + continue; } - } - static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int temp = 0; + while (true) { + newFacing = getFacingFromPointToPoint(curX, curY, toX, toY); + changePosTowardsFacing(curX, curY, newFacing); + // debug drawing + /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) { + screen()->setPagePixel(0, curX, curY, 8); + screen()->updateScreen(); + delayWithTicks(5); + }*/ + + if (!lineIsPassable(curX, curY)) { + if (curX != toX || curY != toY) + continue; + } - if (facing == 0) { - ++facingIsZero[character]; - } else { - bool resetTables = false; - if (facing != 7) { - if (facing - 1 != 0) { - if (facing != 4) { - if (facing == 3 || facing == 5) { - if (facingIsFour[character] > 2) - facing = 4; - resetTables = true; - } - } else { - ++facingIsFour[character]; + if (curX == toX && curY == toY) { + if (!lineIsPassable(curX, curY)) { + tempValue = 0; + temp = 0; + break; } - } else { - if (facingIsZero[character] > 2) - facing = 0; - resetTables = true; } - } else { - if (facingIsZero[character] > 2) - facing = 0; - resetTables = true; - } - - if (resetTables) { - facingIsZero[character] = 0; - facingIsFour[character] = 0; - } - } - - static const uint16 maxAnimationFrame[] = { - 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000, - 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000, - 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000, - 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000, - 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000, - 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000, - 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000 - }; - - if (facing == 0) { - if (maxAnimationFrame[36+character] > ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[36+character]; - if (maxAnimationFrame[30+character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[36+character]; - } else if (facing == 4) { - if (maxAnimationFrame[18+character] > ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[18+character]; - if (maxAnimationFrame[12+character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[18+character]; - } else { - if (maxAnimationFrame[18+character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[30+character]; - if (maxAnimationFrame[character] == ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[6+character]; - if (maxAnimationFrame[character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[6+character]+2; - } - - if (character == 0 && (_brandonStatusBit & 0x10)) - ch->currentAnimFrame = 88; - - _animator->animRefreshNPC(character); -} - -void KyraEngine_v1::loadSceneMsc() { - assert(_currentCharacter->sceneId < _roomTableSize); - int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; - assert(tableId < _roomFilenameTableSize); - char fileNameBuffer[32]; - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".MSC"); - _screen->fillRect(0, 0, 319, 199, 0, 5); - _res->exists(fileNameBuffer, true); - _screen->loadBitmap(fileNameBuffer, 3, 5, 0); -} - -void KyraEngine_v1::startSceneScript(int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::startSceneScript(%d)", brandonAlive); - assert(_currentCharacter->sceneId < _roomTableSize); - int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; - assert(tableId < _roomFilenameTableSize); - char fileNameBuffer[32]; - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".CPS"); - _screen->clearPage(3); - _res->exists(fileNameBuffer, true); - // FIXME: check this hack for amiga version - _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0)); - _sprites->loadSceneShapes(); - _exitListPtr = 0; - - _scaleMode = 1; - for (int i = 0; i < 145; ++i) - _scaleTable[i] = 256; - - clearNoDropRects(); - _emc->init(&_scriptClick, &_scriptClickData); - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".EMC"); - _res->exists(fileNameBuffer, true); - _emc->unload(&_scriptClickData); - _emc->load(fileNameBuffer, &_scriptClickData, &_opcodes); - _emc->start(&_scriptClick, 0); - _scriptClick.regs[0] = _currentCharacter->sceneId; - _scriptClick.regs[7] = brandonAlive; - - while (_emc->isValid(&_scriptClick)) - _emc->run(&_scriptClick); -} - -void KyraEngine_v1::initSceneData(int facing, int unk1, int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive); - - int16 xpos2 = 0; - int setFacing = 1; - - int16 xpos = 0, ypos = 0; - - if (_brandonPosX == -1 && _brandonPosY == -1) { - switch (facing + 1) { - case 0: - xpos = ypos = -1; - break; - - case 1: case 2: case 8: - xpos = _sceneExits.southXPos; - ypos = _sceneExits.southYPos; - break; - - case 3: - xpos = _sceneExits.westXPos; - ypos = _sceneExits.westYPos; - break; - - case 4: case 5: case 6: - xpos = _sceneExits.northXPos; - ypos = _sceneExits.northYPos; - break; - - case 7: - xpos = _sceneExits.eastXPos; - ypos = _sceneExits.eastYPos; - break; - - default: - break; - } - - if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) - ypos = (_northExitHeight & 0xFF) + 4; - if (xpos >= 308) - xpos = 304; - if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) - ypos = (_northExitHeight >> 8) - 4; - if (xpos <= 12) - xpos = 16; - } - - if (_brandonPosX > -1) - xpos = _brandonPosX; - if (_brandonPosY > -1) - ypos = _brandonPosY; - - int16 ypos2 = 0; - if (_brandonPosX > -1 && _brandonPosY > -1) { - switch (_currentCharacter->sceneId) { - case 1: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 4; - xpos2 = 192; - ypos2 = 104; - setFacing = 0; - unk1 = 1; - break; - - case 3: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 2; - xpos2 = 204; - ypos2 = 94; - setFacing = 0; - unk1 = 1; - break; - - case 26: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 2; - xpos2 = 192; - ypos2 = 128; - setFacing = 0; - unk1 = 1; - break; - - case 44: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 6; - xpos2 = 156; - ypos2 = 96; - setFacing = 0; - unk1 = 1; - break; - - case 37: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 2; - xpos2 = 148; - ypos2 = 114; - setFacing = 0; - unk1 = 1; - break; - - default: - break; - } - } - - _brandonPosX = _brandonPosY = -1; - - if (unk1 && setFacing) { - ypos2 = ypos; - xpos2 = xpos; - switch (facing) { - case 0: - ypos = 142; - break; - - case 2: - xpos = -16; - break; - - case 4: - ypos = (uint8)(_northExitHeight & 0xFF) - 4; - break; - - case 6: - xpos = 336; - break; - - default: - break; - } - } - - xpos2 = (int16)(xpos2 & 0xFFFC); - ypos2 = (int16)(ypos2 & 0xFFFE); - xpos = (int16)(xpos & 0xFFFC); - ypos = (int16)(ypos & 0xFFFE); - _currentCharacter->facing = facing; - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - - initSceneObjectList(brandonAlive); - - if (unk1 && brandonAlive == 0) - moveCharacterToPos(0, facing, xpos2, ypos2); - - _scriptClick.regs[4] = _itemInHand; - _scriptClick.regs[7] = brandonAlive; - _emc->start(&_scriptClick, 3); - while (_emc->isValid(&_scriptClick)) - _emc->run(&_scriptClick); -} - -void KyraEngine_v1::initSceneObjectList(int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::initSceneObjectList(%d)", brandonAlive); - for (int i = 0; i < 28; ++i) - _animator->actors()[i].active = 0; - - int startAnimFrame = 0; - - Animator_v1::AnimObject *curAnimState = _animator->actors(); - curAnimState->active = 1; - curAnimState->drawY = _currentCharacter->y1; - curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame]; - curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame; - startAnimFrame = _currentCharacter->currentAnimFrame-7; - int xOffset = _defaultShapeTable[startAnimFrame].xOffset; - int yOffset = _defaultShapeTable[startAnimFrame].yOffset; - - if (_scaleMode) { - curAnimState->x1 = _currentCharacter->x1; - curAnimState->y1 = _currentCharacter->y1; - - _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1]; - _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1]; - - curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; - curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; - } else { - curAnimState->x1 = _currentCharacter->x1 + xOffset; - curAnimState->y1 = _currentCharacter->y1 + yOffset; - } - - curAnimState->x2 = curAnimState->x1; - curAnimState->y2 = curAnimState->y1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - _animator->clearQueue(); - _animator->addObjectToQueue(curAnimState); - - int listAdded = 0; - int addedObjects = 1; - - for (int i = 1; i < 5; ++i) { - Character *ch = &_characterList[i]; - curAnimState = &_animator->actors()[addedObjects]; - if (ch->sceneId != _currentCharacter->sceneId) { - curAnimState->active = 0; - curAnimState->refreshFlag = 0; - curAnimState->bkgdChangeFlag = 0; - ++addedObjects; - continue; - } - - curAnimState->drawY = ch->y1; - curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame]; - curAnimState->animFrameNumber = ch->currentAnimFrame; - startAnimFrame = ch->currentAnimFrame-7; - xOffset = _defaultShapeTable[startAnimFrame].xOffset; - yOffset = _defaultShapeTable[startAnimFrame].yOffset; - if (_scaleMode) { - curAnimState->x1 = ch->x1; - curAnimState->y1 = ch->y1; - _animator->_brandonScaleX = _scaleTable[ch->y1]; - _animator->_brandonScaleY = _scaleTable[ch->y1]; - - curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; - curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; - } else { - curAnimState->x1 = ch->x1 + xOffset; - curAnimState->y1 = ch->y1 + yOffset; - } - curAnimState->x2 = curAnimState->x1; - curAnimState->y2 = curAnimState->y1; - curAnimState->active = 1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - - if (ch->facing >= 1 && ch->facing <= 3) - curAnimState->flags |= 1; - else if (ch->facing >= 5 && ch->facing <= 7) - curAnimState->flags &= 0xFFFFFFFE; - - _animator->addObjectToQueue(curAnimState); - - ++addedObjects; - ++listAdded; - if (listAdded < 2) - i = 5; - } - - for (int i = 0; i < 11; ++i) { - curAnimState = &_animator->sprites()[i]; - - if (_sprites->_anims[i].play) { - curAnimState->active = 1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - } else { - curAnimState->active = 0; - curAnimState->refreshFlag = 0; - curAnimState->bkgdChangeFlag = 0; - } - curAnimState->height = _sprites->_anims[i].height; - curAnimState->height2 = _sprites->_anims[i].height2; - curAnimState->width = _sprites->_anims[i].width + 1; - curAnimState->width2 = _sprites->_anims[i].width2; - curAnimState->drawY = _sprites->_anims[i].drawY; - curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x; - curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y; - curAnimState->background = _sprites->_anims[i].background; - curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite]; - - curAnimState->disable = _sprites->_anims[i].disable; - - if (_sprites->_anims[i].unk2) - curAnimState->flags = 0x800; - else - curAnimState->flags = 0; - - if (_sprites->_anims[i].flipX) - curAnimState->flags |= 0x1; - - _animator->addObjectToQueue(curAnimState); - } - - for (int i = 0; i < 12; ++i) { - curAnimState = &_animator->items()[i]; - Room *curRoom = &_roomTable[_currentCharacter->sceneId]; - byte curItem = curRoom->itemsTable[i]; - if (curItem != 0xFF) { - curAnimState->drawY = curRoom->itemsYPos[i]; - curAnimState->sceneAnimPtr = _shapes[216+curItem]; - curAnimState->animFrameNumber = (int16)0xFFFF; - curAnimState->y1 = curRoom->itemsYPos[i]; - curAnimState->x1 = curRoom->itemsXPos[i]; - - curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1; - curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]); - - curAnimState->x2 = curAnimState->x1; - curAnimState->y2 = curAnimState->y1; - - curAnimState->active = 1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - - _animator->addObjectToQueue(curAnimState); - } else { - curAnimState->active = 0; - curAnimState->refreshFlag = 0; - curAnimState->bkgdChangeFlag = 0; - } - } - - _animator->preserveAnyChangedBackgrounds(); - curAnimState = _animator->actors(); - curAnimState->bkgdChangeFlag = 1; - curAnimState->refreshFlag = 1; - for (int i = 1; i < 28; ++i) { - curAnimState = &_animator->objects()[i]; - if (curAnimState->active) { - curAnimState->bkgdChangeFlag = 1; - curAnimState->refreshFlag = 1; - } - } - _animator->restoreAllObjectBackgrounds(); - _animator->preserveAnyChangedBackgrounds(); - _animator->prepDrawAllObjects(); - initSceneScreen(brandonAlive); - _animator->copyChangedObjectsForward(0); -} + temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0); + tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0); + if (curX == toX && curY == toY) { + if (temp == 0x7D00 && tempValue == 0x7D00) { + delete[] pathTable1; + delete[] pathTable2; + return 0x7D00; + } + } -void KyraEngine_v1::initSceneScreen(int brandonAlive) { - if (_flags.platform == Common::kPlatformAmiga) { - if (_unkScreenVar1 && !queryGameFlag(0xF0)) { - memset(_screen->getPalette(2), 0, 32*3); - if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3)) - _screen->setScreenPalette(_screen->getPalette(2)); + if (temp != 0x7D00 || tempValue != 0x7D00) + break; } - if (_unkScreenVar2 == 1) - _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); - else - _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); - - if (_unkScreenVar1 && !queryGameFlag(0xA0)) { - if (_currentCharacter->sceneId == 45 && _paletteChanged) - memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2); - - if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64); - - _screen->setScreenPalette(_screen->getPalette(0)); - } - } else { - if (_unkScreenVar1 && !queryGameFlag(0xA0)) { - for (int i = 0; i < 60; ++i) { - uint16 col = _screen->getPalette(0)[684+i]; - col += _screen->getPalette(1)[684+i] << 1; - col >>= 2; - _screen->getPalette(0)[684+i] = col; + if (temp < tempValue) { + if (lastUsedEntry + temp > moveTableSize) { + delete[] pathTable1; + delete[] pathTable2; + return 0x7D00; } - _screen->setScreenPalette(_screen->getPalette(0)); - } - - if (_unkScreenVar2 == 1) - _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); - else - _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); - - if (_unkScreenVar1 && _paletteChanged) { - if (!queryGameFlag(0xA0)) { - memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60); - _screen->setScreenPalette(_screen->getPalette(0)); - } else { - memset(_screen->getPalette(0), 0, 768); + memcpy(&moveTable[lastUsedEntry], pathTable1, temp*sizeof(int)); + lastUsedEntry += temp; + } else { + if (lastUsedEntry + tempValue > moveTableSize) { + delete[] pathTable1; + delete[] pathTable2; + return 0x7D00; } + memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue*sizeof(int)); + lastUsedEntry += tempValue; } + x = curX; + y = curY; + if (curX == toX && curY == toY) + break; } - if (!_emc->start(&_scriptClick, 2)) - error("Could not start script function 2 of scene script"); - - _scriptClick.regs[7] = brandonAlive; - - while (_emc->isValid(&_scriptClick)) - _emc->run(&_scriptClick); - - setTextFadeTimerCountdown(-1); - if (_currentCharacter->sceneId == 210) { - if (_itemInHand != -1) - magicOutMouseItem(2, -1); - - _screen->hideMouse(); - for (int i = 0; i < 10; ++i) { - if (_currentCharacter->inventoryItems[i] != 0xFF) - magicOutMouseItem(2, i); - } - _screen->showMouse(); - } -} - -int KyraEngine_v1::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset); - if (queryGameFlag(0xEF)) - unk1 = 0; - - int sceneId = _currentCharacter->sceneId; - _pathfinderFlag = 0; - - if (xpos < 12) { - if (_roomTable[sceneId].westExit != 0xFFFF) { - xpos = 12; - ypos = _sceneExits.westYPos; - _pathfinderFlag = 7; - } - } else if (xpos >= 308) { - if (_roomTable[sceneId].eastExit != 0xFFFF) { - xpos = 307; - ypos = _sceneExits.eastYPos; - _pathfinderFlag = 13; - } - } - - if (ypos <= (_northExitHeight&0xFF)+2) { - if (_roomTable[sceneId].northExit != 0xFFFF) { - xpos = _sceneExits.northXPos; - ypos = _northExitHeight & 0xFF; - _pathfinderFlag = 14; - } - } else if (ypos >= 136) { - if (_roomTable[sceneId].southExit != 0xFFFF) { - xpos = _sceneExits.southXPos; - ypos = 136; - _pathfinderFlag = 11; - } - } - - int temp = xpos - _currentCharacter->x1; - if (ABS(temp) < 4) { - temp = ypos - _currentCharacter->y1; - if (ABS(temp) < 2) - return 0; - } - - int x = (int16)(_currentCharacter->x1 & 0xFFFC); - int y = (int16)(_currentCharacter->y1 & 0xFFFE); - xpos = (int16)(xpos & 0xFFFC); - ypos = (int16)(ypos & 0xFFFE); - - int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150); - _pathfinderFlag = 0; - - if (ret >= _lastFindWayRet) - _lastFindWayRet = ret; - - if (ret == 0x7D00 || ret == 0) - return 0; - - return processSceneChange(_movFacingTable, unk1, frameReset); + delete[] pathTable1; + delete[] pathTable2; + moveTable[lastUsedEntry] = 8; + return lastUsedEntry; } -int KyraEngine_v1::processSceneChange(int *table, int unk1, int frameReset) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::processSceneChange(%p, %d, %d)", (const void *)table, unk1, frameReset); - if (queryGameFlag(0xEF)) - unk1 = 0; - - int *tableStart = table; - _sceneChangeState = 0; - _loopFlag2 = 0; - bool running = true; - int returnValue = 0; - uint32 nextFrame = 0; - _abortWalkFlag = false; - _mousePressFlag = false; - - while (running) { - if (_abortWalkFlag) { - *table = 8; - _currentCharacter->currentAnimFrame = 7; - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - processInput(); - return 0; - } - bool forceContinue = false; - switch (*table) { - case 0: case 1: case 2: - case 3: case 4: case 5: - case 6: case 7: - _currentCharacter->facing = getOppositeFacingDirection(*table); - break; - - case 8: - forceContinue = true; - running = false; - break; - - default: - ++table; - forceContinue = true; +int KyraEngine_v1::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::findSubPath(%d, %d, %d, %d, %p, %d, %d)", x, y, toX, toY, (const void *)moveTable, start, end); + // only used for debug specific code + //static uint16 unkTable[] = { 8, 5 }; + static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 }; + static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 }; + static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 }; + static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 }; + static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 }; + + // debug specific + /*++unkTable[start]; + while (screen()->getPalette(0)[unkTable[start]] != 0x0F) { + ++unkTable[start]; + }*/ + + int xpos1 = x, xpos2 = x; + int ypos1 = y, ypos2 = y; + int newFacing = getFacingFromPointToPoint(x, y, toX, toY); + int position = 0; + + while (position != end) { + int newFacing2 = newFacing; + while (true) { + changePosTowardsFacing(xpos1, ypos1, facingTable1[start*8 + newFacing2]); + if (!lineIsPassable(xpos1, ypos1)) { + if (facingTable1[start*8 + newFacing2] == newFacing) + return 0x7D00; + newFacing2 = facingTable1[start*8 + newFacing2]; + xpos1 = x; + ypos1 = y; + continue; + } + newFacing = facingTable1[start*8 + newFacing2]; break; } - - returnValue = changeScene(_currentCharacter->facing); - if (returnValue) { - running = false; - _abortWalkFlag = false; - } - - if (unk1) { - if (_mousePressFlag) { - running = false; - _sceneChangeState = 1; + // debug drawing + /*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) { + screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]); + screen()->updateScreen(); + delayWithTicks(5); + }*/ + if (newFacing & 1) { + int temp = xpos1 + addPosTableX[newFacing + start * 8]; + if (toX == temp) { + temp = ypos1 + addPosTableY[newFacing + start * 8]; + if (toY == temp) { + moveTable[position++] = facingTable2[newFacing + start * 8]; + return position; + } } } - if (forceContinue || !running) - continue; - - int temp = 0; - if (table == tableStart || table[1] == 8) - temp = setCharacterPosition(0, 0); - else - temp = setCharacterPosition(0, table); - - if (temp) - ++table; + moveTable[position++] = newFacing; + x = xpos1; + y = ypos1; - nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis(); - while (_system->getMillis() < nextFrame) { - _timer->update(); + if (x == toX && y == toY) + return position; - if (_currentCharacter->sceneId == 210) { - updateKyragemFading(); - if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) { - *table = 8; - running = false; - break; - } - } + if (xpos1 == xpos2 && ypos1 == ypos2) + break; - if ((nextFrame - _system->getMillis()) >= 10) - delay(10, true); - } + newFacing = facingTable3[start*8 + newFacing]; } - if (frameReset && !(_brandonStatusBit & 2)) - _currentCharacter->currentAnimFrame = 7; - - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - return returnValue; + return 0x7D00; } -int KyraEngine_v1::changeScene(int facing) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::changeScene(%d)", facing); - if (queryGameFlag(0xEF)) { - if (_currentCharacter->sceneId == 5) - return 0; - } - - int xpos = _charXPosTable[facing] + _currentCharacter->x1; - int ypos = _charYPosTable[facing] + _currentCharacter->y1; +int KyraEngine_v1::getFacingFromPointToPoint(int x, int y, int toX, int toY) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::getFacingFromPointToPoint(%d, %d, %d, %d)", x, y, toX, toY); + static const int facingTable[] = { + 1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6 + }; - if (xpos >= 12 && xpos <= 308) { - if (!lineIsPassable(xpos, ypos)) - return false; + int facingEntry = 0; + int ydiff = y - toY; + if (ydiff < 0) { + ++facingEntry; + ydiff = -ydiff; } + facingEntry <<= 1; - if (_exitListPtr) { - int16 *ptr = _exitListPtr; - // this loop should be only entered one time, seems to be some hack in the original - while (true) { - if (*ptr == -1) - break; - - if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) { - ptr += 10; - break; - } - - _brandonPosX = ptr[6]; - _brandonPosY = ptr[7]; - uint16 sceneId = ptr[5]; - facing = ptr[4]; - int unk1 = ptr[8]; - int unk2 = ptr[9]; - - if (sceneId == 0xFFFF) { - switch (facing) { - case 0: - sceneId = _roomTable[_currentCharacter->sceneId].northExit; - break; - - case 2: - sceneId = _roomTable[_currentCharacter->sceneId].eastExit; - break; - - case 4: - sceneId = _roomTable[_currentCharacter->sceneId].southExit; - break; - - case 6: - sceneId = _roomTable[_currentCharacter->sceneId].westExit; - break; - - default: - break; - } - } - - _currentCharacter->facing = facing; - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - enterNewScene(sceneId, facing, unk1, unk2, 0); - resetGameFlag(0xEE); - return 1; - } + int xdiff = toX - x; + if (xdiff < 0) { + ++facingEntry; + xdiff = -xdiff; } - int returnValue = 0; - facing = 0; + if (xdiff >= ydiff) { + int temp = ydiff; + ydiff = xdiff; + xdiff = temp; - if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) { - facing = 0; - returnValue = 1; + facingEntry <<= 1; + } else { + facingEntry <<= 1; + facingEntry += 1; } + int temp = (ydiff + 1) >> 1; - if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) { - facing = 2; - returnValue = 1; + if (xdiff < temp) { + facingEntry <<= 1; + facingEntry += 1; + } else { + facingEntry <<= 1; } - if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) { - facing = 4; - returnValue = 1; - } + assert(facingEntry < ARRAYSIZE(facingTable)); + return facingTable[facingEntry]; +} - if (xpos <= 12 || _currentCharacter->y1 <= 12) { - facing = 6; - returnValue = 1; - } - if (!returnValue) - return 0; - - uint16 sceneId = 0xFFFF; - switch (facing) { +int KyraEngine_v1::getOppositeFacingDirection(int dir) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::getOppositeFacingDirection(%d)", dir); + switch (dir) { case 0: - sceneId = _roomTable[_currentCharacter->sceneId].northExit; - break; - - case 2: - sceneId = _roomTable[_currentCharacter->sceneId].eastExit; - break; - + return 2; + case 1: + return 1; + case 3: + return 7; case 4: - sceneId = _roomTable[_currentCharacter->sceneId].southExit; - break; - + return 6; + case 5: + return 5; + case 6: + return 4; + case 7: + return 3; default: - sceneId = _roomTable[_currentCharacter->sceneId].westExit; break; } - - if (sceneId == 0xFFFF) - return 0; - - enterNewScene(sceneId, facing, 1, 1, 0); - return returnValue; -} - -void KyraEngine_v1::setCharactersInDefaultScene() { - static const uint32 defaultSceneTable[][4] = { - { 0xFFFF, 0x0004, 0x0003, 0xFFFF }, - { 0xFFFF, 0x0022, 0xFFFF, 0x0000 }, - { 0xFFFF, 0x001D, 0x0021, 0xFFFF }, - { 0xFFFF, 0x0000, 0x0000, 0xFFFF } - }; - - for (int i = 1; i < 5; ++i) { - Character *cur = &_characterList[i]; - //cur->field_20 = 0; - - const uint32 *curTable = defaultSceneTable[i-1]; - cur->sceneId = curTable[0]; - - if (cur->sceneId == _currentCharacter->sceneId) - //++cur->field_20; - cur->sceneId = curTable[1/*cur->field_20*/]; - - //cur->field_23 = curTable[cur->field_20+1]; - } + return 0; } -void KyraEngine_v1::setCharactersPositions(int character) { - static uint16 initXPosTable[] = { - 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B, - 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042 - }; - static uint8 initYPosTable[] = { - 0x00, 0xA2, 0x00, 0x42, 0x00, - 0x67, 0x67, 0x60, 0x5A, 0x71, - 0x76 - }; - - assert(character < ARRAYSIZE(initXPosTable)); - Character *edit = &_characterList[character]; - edit->x1 = edit->x2 = initXPosTable[character]; - edit->y1 = edit->y2 = initYPosTable[character]; +void KyraEngine_v1::changePosTowardsFacing(int &x, int &y, int facing) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::changePosTowardsFacing(%d, %d, %d)", x, y, facing); + x += _addXPosTable[facing]; + y += _addYPosTable[facing]; } -#pragma mark - -#pragma mark - Pathfinder -#pragma mark - - -int KyraEngine_v1::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); - int ret = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize); - if (ret == 0x7D00) +int KyraEngine_v1::getMoveTableSize(int *moveTable) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::getMoveTableSize(%p)", (const void *)moveTable); + int retValue = 0; + if (moveTable[0] == 8) return 0; - return getMoveTableSize(moveTable); -} - -bool KyraEngine_v1::lineIsPassable(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::lineIsPassable(%d, %d)", x, y); - if (queryGameFlag(0xEF)) { - if (_currentCharacter->sceneId == 5) - return true; - } - - if (_pathfinderFlag & 2) { - if (x >= 312) - return false; - } - if (_pathfinderFlag & 4) { - if (y >= 136) - return false; - } + static const int facingTable[] = { + 4, 5, 6, 7, 0, 1, 2, 3 + }; + static const int unkTable[] = { + -1, -1, 1, 2, -1, 6, 7, -1, + -1, -1, -1, -1, 2, -1, 0, -1, + 1, -1, -1, -1, 3, 4, -1, 0, + 2, -1, -1, -1, -1, -1, 4, -1, + -1, 2, 3, -1, -1, -1, 5, 6, + 6, -1, 4, -1, -1, -1, -1, -1, + 7, 0, -1, 4, 5, -1, -1, -1, + -1, -1, 0, -1, 6, -1, -1, -1 + }; - if (_pathfinderFlag & 8) { - if (x < 8) - return false; - } + int *oldPosition = moveTable; + int *tempPosition = moveTable; + int *curPosition = moveTable + 1; + retValue = 1; - if (_pathfinderFlag2) { - if (x <= 8 || x >= 312) - return true; - if (y < (_northExitHeight & 0xFF) || y > 135) - return true; - } + while (*curPosition != 8) { + if (*oldPosition == facingTable[*curPosition]) { + retValue -= 2; + *oldPosition = 9; + *curPosition = 9; - if (y > 137) - return false; - - if (y < 0) - y = 0; + while (tempPosition != moveTable) { + --tempPosition; + if (*tempPosition != 9) + break; + } - int ypos = 8; - if (_scaleMode) { - ypos = (_scaleTable[y] >> 5) + 1; - if (8 < ypos) - ypos = 8; - } + if (tempPosition == moveTable && *tempPosition == 9) { + while (*tempPosition != 8 && *tempPosition == 9) + ++tempPosition; - x -= (ypos >> 1); + if (*tempPosition == 8) + return 0; + } - int xpos = x; - int xtemp = xpos + ypos - 1; - if (x < 0) - xpos = 0; + oldPosition = tempPosition; + curPosition = oldPosition+1; - if (xtemp > 319) - xtemp = 319; + while (*curPosition != 8 && *curPosition == 9) + ++curPosition; - for (; xpos < xtemp; ++xpos) { - if (!_screen->getShapeFlag1(xpos, y)) - return false; - } - return true; -} + continue; + } -#pragma mark - + if (unkTable[*curPosition+((*oldPosition)*8)] != -1) { + --retValue; + *oldPosition = unkTable[*curPosition+((*oldPosition)*8)]; + *curPosition = 9; -void KyraEngine_v1::setupSceneResource(int sceneId) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setupSceneResource(%d)", sceneId); - if (!_flags.isTalkie) - return; + if (tempPosition != oldPosition) { + curPosition = oldPosition; + oldPosition = tempPosition; + while (true) { + if (tempPosition == moveTable) + break; - if (_currentRoom != 0xFFFF) { - assert(_currentRoom < _roomTableSize); - int tableId = _roomTable[_currentRoom].nameIndex; - assert(tableId < _roomFilenameTableSize); + --tempPosition; + if (*tempPosition != 9) + break; - // unload our old room - char file[64]; - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".VRM"); - _res->unloadPakFile(file); + } + } else { + while (true) { + ++curPosition; + if (*curPosition != 9) + break; + } + } + continue; + } - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".PAK"); - _res->unloadPakFile(file); + tempPosition = oldPosition; + oldPosition = curPosition; + ++retValue; - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".APK"); - _res->unloadPakFile(file); + while (true) { + ++curPosition; + if (*curPosition != 9) + break; + } } - assert(sceneId < _roomTableSize); - int tableId = _roomTable[sceneId].nameIndex; - assert(tableId < _roomFilenameTableSize); - - // load our new room - char file[64]; - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".VRM"); - if (_res->exists(file)) - _res->loadPakFile(file); - - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".PAK"); - if (_res->exists(file)) - _res->loadPakFile(file); - - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".APK"); - if (_res->exists(file)) - _res->loadPakFile(file); + return retValue; } } // end of namespace Kyra - diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp index 5d811bcf44..3bf81bfb39 100644 --- a/engines/kyra/scene_v2.cpp +++ b/engines/kyra/scene_v2.cpp @@ -90,7 +90,7 @@ int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int m debugC(9, kDebugLevelMain, "KyraEngine_v2::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); x &= ~3; toX &= ~3; y &= ~1; toY &= ~1; - int size = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize); + int size = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize); static bool usePostProcess = false; if (size && !usePostProcess) { usePostProcess = true; @@ -98,7 +98,7 @@ int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int m temp = pathfinderInitPositionIndexTable(temp, x, y); pathfinderFinializePath(moveTable, temp, x, y, moveTableSize); usePostProcess = false; - } + } return usePostProcess ? size : getMoveTableSize(moveTable); } @@ -106,13 +106,14 @@ bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) { debugC(9, kDebugLevelMain, "KyraEngine_v2::directLinePassable(%d, %d, %d, %d)", x, y, toX, toY); Screen *scr = screen(); - while (x != toX && y != toY) { + while (x != toX || y != toY) { int facing = getFacingFromPointToPoint(x, y, toX, toY); x += _addXPosTable[facing]; y += _addYPosTable[facing]; if (!scr->getShapeFlag1(x, y)) return false; } + return true; } diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 298483465e..f00c47ceea 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -28,40 +28,41 @@ #include "common/system.h" #include "graphics/cursorman.h" #include "kyra/screen.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/resource.h" namespace Kyra { -Screen::Screen(KyraEngine *vm, OSystem *system) +Screen::Screen(KyraEngine_v1 *vm, OSystem *system) : _system(system), _vm(vm), _sjisInvisibleColor(0) { _debugEnabled = false; + _maskMinY = _maskMaxY = -1; } Screen::~Screen() { for (int i = 0; i < SCREEN_OVLS_NUM; ++i) - delete [] _sjisOverlayPtrs[i]; + delete[] _sjisOverlayPtrs[i]; - delete [] _pagePtrs[0]; + delete[] _pagePtrs[0]; for (int f = 0; f < ARRAYSIZE(_fonts); ++f) { delete[] _fonts[f].fontData; _fonts[f].fontData = NULL; } - delete [] _sjisFontData; - delete [] _sjisTempPage; - delete [] _currentPalette; - delete [] _screenPalette; - delete [] _decodeShapeBuffer; - delete [] _animBlockPtr; + delete[] _sjisFontData; + delete[] _sjisTempPage; + delete[] _currentPalette; + delete[] _screenPalette; + delete[] _decodeShapeBuffer; + delete[] _animBlockPtr; if (_vm->gameFlags().platform != Common::kPlatformAmiga) { for (int i = 0; i < ARRAYSIZE(_palettes); ++i) - delete [] _palettes[i]; + delete[] _palettes[i]; } - delete [] _dirtyRects; + delete[] _dirtyRects; } bool Screen::init() { @@ -307,14 +308,16 @@ const uint8 *Screen::getCPagePtr(int pageNum) const { uint8 *Screen::getPageRect(int pageNum, int x, int y, int w, int h) { debugC(9, kDebugLevelScreen, "Screen::getPageRect(%d, %d, %d, %d, %d)", pageNum, x, y, w, h); assert(pageNum < SCREEN_PAGE_NUM); - if (pageNum == 0 || pageNum == 1) addDirtyRect(x, y, w, h); + if (pageNum == 0 || pageNum == 1) + addDirtyRect(x, y, w, h); return _pagePtrs[pageNum] + y * SCREEN_W + x; } void Screen::clearPage(int pageNum) { debugC(9, kDebugLevelScreen, "Screen::clearPage(%d)", pageNum); assert(pageNum < SCREEN_PAGE_NUM); - if (pageNum == 0 || pageNum == 1) _forceFullUpdate = true; + if (pageNum == 0 || pageNum == 1) + _forceFullUpdate = true; memset(getPagePtr(pageNum), 0, SCREEN_PAGE_SIZE); clearOverlayPage(pageNum); } @@ -329,7 +332,8 @@ int Screen::setCurPage(int pageNum) { void Screen::clearCurPage() { debugC(9, kDebugLevelScreen, "Screen::clearCurPage()"); - if (_curPage == 0 || _curPage == 1) _forceFullUpdate = true; + if (_curPage == 0 || _curPage == 1) + _forceFullUpdate = true; memset(getPagePtr(_curPage), 0, SCREEN_PAGE_SIZE); clearOverlayPage(_curPage); } @@ -478,7 +482,7 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { } addDirtyRect(0, y, SCREEN_W, h); // This would remove the text in the end sequence of - // the FM-Towns version. + // the (Kyrandia 1) FM-Towns version. // Since this method is just used for the Seqplayer // this shouldn't be a problem anywhere else, so it's // safe to disable the call here. @@ -576,7 +580,8 @@ void Screen::copyPage(uint8 srcPage, uint8 dstPage) { memcpy(dst, src, SCREEN_W * SCREEN_H); copyOverlayRegion(0, 0, 0, 0, SCREEN_W, SCREEN_H, srcPage, dstPage); - if (dstPage == 0 || dstPage == 1) _forceFullUpdate = true; + if (dstPage == 0 || dstPage == 1) + _forceFullUpdate = true; } void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint8 *src) { @@ -843,7 +848,7 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) { void Screen::setAnimBlockPtr(int size) { debugC(9, kDebugLevelScreen, "Screen::setAnimBlockPtr(%d)", size); - delete [] _animBlockPtr; + delete[] _animBlockPtr; _animBlockPtr = new uint8[size]; assert(_animBlockPtr); memset(_animBlockPtr, 0, size); @@ -867,18 +872,18 @@ bool Screen::loadFont(FontId fontId, const char *filename) { error("fontId %d is invalid", fontId); if (fnt->fontData) - delete [] fnt->fontData; + delete[] fnt->fontData; uint32 sz = 0; uint8 *fontData = fnt->fontData = _vm->resource()->fileData(filename, &sz); if (!fontData || !sz) - error("couldn't load font file '%s'", filename); + error("Couldn't load font file '%s'", filename); uint16 fontSig = READ_LE_UINT16(fontData + 2); if (fontSig != 0x500) - error("Invalid font data (file '%s')", filename); + error("Invalid font data (file '%s', fontSig: %.04X)", filename, fontSig); fnt->charWidthTable = fontData + READ_LE_UINT16(fontData + 8); fnt->charSizeOffset = READ_LE_UINT16(fontData + 4); @@ -934,15 +939,14 @@ int Screen::getTextWidth(const char *str) const { if (c == 0) { break; } else if (c == '\r') { - if (curLineLen > maxLineLen) { + if (curLineLen > maxLineLen) maxLineLen = curLineLen; - } else { + else curLineLen = 0; - } } else { - if (c <= 0x7F || !_useSJIS) + if (c <= 0x7F || !_useSJIS) { curLineLen += getCharWidth(c); - else { + } else { c = READ_LE_UINT16(str - 1); ++str; curLineLen += getCharWidth(c); @@ -1894,11 +1898,10 @@ void Screen::wrapped_decodeFrameDelta(uint8 *dst, const uint8 *src) { void Screen::decodeFrameDeltaPage(uint8 *dst, const uint8 *src, int pitch, bool noXor) { debugC(9, kDebugLevelScreen, "Screen::decodeFrameDeltaPage(%p, %p, %d, %d)", (const void *)dst, (const void *)src, pitch, noXor); - if (noXor) { + if (noXor) wrapped_decodeFrameDeltaPage<true>(dst, src, pitch); - } else { + else wrapped_decodeFrameDeltaPage<false>(dst, src, pitch); - } } void Screen::convertAmigaGfx(uint8 *data, int w, int h, bool offscreen) { @@ -1933,7 +1936,7 @@ void Screen::convertAmigaGfx(uint8 *data, int w, int h, bool offscreen) { for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { int bytePos = x/8+y*40; - int bitPos = 7-x&7; + int bitPos = 7-(x&7); byte colorIndex = 0; colorIndex |= (((tmp[bytePos + 8000 * 0] & (1 << bitPos)) >> bitPos) & 0x1) << 0; @@ -2235,7 +2238,7 @@ uint8 *Screen::encodeShape(int x, int y, int w, int h, int flags) { uint8 *newShape2 = new uint8[shapeSize]; assert(newShape2); memcpy(newShape2, newShape, shapeSize); - delete [] newShape; + delete[] newShape; newShape = newShape2; } else { dst = shapePtrBackUp; @@ -2469,7 +2472,7 @@ void Screen::setMouseCursor(int x, int y, byte *shape) { copyRegionToBuffer(8, xOffset, 0, mouseWidth, mouseHeight, cursor); CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, 0); CursorMan.showMouse(true); - delete [] cursor; + delete[] cursor; // makes sure that the cursor is drawn // we do not use Screen::updateScreen here @@ -2642,7 +2645,7 @@ void Screen::shakeScreen(int times) { } void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip) { - debugC(9, kDebugLevelScreen, "KyraEngine::loadBitmap('%s', %d, %d, %p, %d)", filename, tempPage, dstPage, (void *)palData, skip); + debugC(9, kDebugLevelScreen, "KyraEngine_v1::loadBitmap('%s', %d, %d, %p, %d)", filename, tempPage, dstPage, (void *)palData, skip); uint32 fileSize; uint8 *srcData = _vm->resource()->fileData(filename, &fileSize); @@ -2694,7 +2697,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 * if (skip) srcData -= 4; - delete [] srcData; + delete[] srcData; } bool Screen::loadPalette(const char *filename, uint8 *palData) { @@ -2722,7 +2725,7 @@ bool Screen::loadPalette(const char *filename, uint8 *palData) { memcpy(palData, srcData, fileSize); } } - delete [] srcData; + delete[] srcData; return true; } diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index bf23747daf..f8c85a2bac 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -35,7 +35,7 @@ namespace Kyra { typedef Common::Functor0<void> UpdateFunctor; -class KyraEngine; +class KyraEngine_v1; struct Rect { int x, y; @@ -96,7 +96,7 @@ public: FID_NUM }; - Screen(KyraEngine *vm, OSystem *system); + Screen(KyraEngine_v1 *vm, OSystem *system); virtual ~Screen(); // init @@ -301,7 +301,7 @@ protected: void addDirtyRect(int x, int y, int w, int h); OSystem *_system; - KyraEngine *_vm; + KyraEngine_v1 *_vm; // shape int drawShapeMarginNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt); diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp index 9192626159..2378c870a8 100644 --- a/engines/kyra/screen_hof.cpp +++ b/engines/kyra/screen_hof.cpp @@ -31,13 +31,7 @@ namespace Kyra { Screen_HoF::Screen_HoF(KyraEngine_HoF *vm, OSystem *system) - : Screen_v2(vm, system) { - _vm = vm; - _wsaFrameAnimBuffer = new uint8[1024]; -} - -Screen_HoF::~Screen_HoF() { - delete [] _wsaFrameAnimBuffer; + : Screen_v2(vm, system), _vm(vm) { } void Screen_HoF::setScreenDim(int dim) { @@ -74,80 +68,10 @@ void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor); } -void Screen_HoF::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, - int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim) { - - if (!(w1 || h1 || w2 || h2)) - return; - - ScreenDim cdm = _screenDimTable[dim]; - cdm.sx <<= 3; - cdm.w <<= 3; - - int na = 0, nb = 0, nc = w2; - - if (!calcBounds(cdm.w, cdm.h, x2, y2, w2, h2, na, nb, nc)) - return; - - const uint8 *src = getPagePtr(srcPage) + y1 * 320; - uint8 *dst = getPagePtr(dstPage) + (y2 + cdm.sy) * 320; - - int u = -1; - - do { - int t = (nb * h1) / h2; - if (t != u) { - u = t; - const uint8 *s = src + (x1 + t) * 320; - uint8 *dt = (uint8*) _wsaFrameAnimBuffer; - - t = w2 - w1; - if (!t) { - memcpy(dt, s, w2); - } else if (t > 0) { - if (w1 == 1) { - memset(dt, *s, w2); - } else { - t = ((((((w2 - w1 + 1) & 0xffff) << 8) / w1) + 0x100) & 0xffff) << 8; - int bp = 0; - for (int i = 0; i < w1; i++) { - int cnt = (t >> 16); - bp += (t & 0xffff); - if (bp > 0xffff) { - bp -= 0xffff; - cnt++; - } - memset(dt, *s++, cnt); - dt += cnt; - } - } - } else { - if (w2 == 1) { - *dt = *s; - } else { - t = (((((w1 - w2) & 0xffff) << 8) / w2) & 0xffff) << 8; - int bp = 0; - for (int i = 0; i < w2; i++) { - *dt++ = *s++; - bp += (t & 0xffff); - if (bp > 0xffff) { - bp -= 0xffff; - s++; - } - s += (t >> 16); - } - } - } - } - memcpy(dst + x2 + cdm.sx, _wsaFrameAnimBuffer + na, w2); - dst += 320; - } while (++nb < h2); -} - void Screen_HoF::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage) { - if (!(cmpW || cmpH )) + if (!cmpW || !cmpH) return; int r1, r2, r3, r4, r5, r6; @@ -192,8 +116,7 @@ void Screen_HoF::copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos memcpy(dst, src, numBytes); } - -void Screen_HoF::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *dim, bool flag) { +void Screen_HoF::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX, int dstY, int dstW, int dstH, const ScreenDim *dim, bool flag) { int x0 = dim->sx << 3; int y0 = dim->sy; int w0 = dim->w << 3; @@ -229,51 +152,5 @@ void Screen_HoF::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int } } -bool Screen_HoF::calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2) { - x2 = 0; - y2 = 0; - w2 = w1; - - int t = x1 + w1; - if (t < 1) { - w1 = h1 = -1; - } else { - if (t <= x1) { - x2 = w1 - t; - w1 = t; - x1 = 0; - } - t = w0 - x1; - if (t < 1) { - w1 = h1 = -1; - } else { - if (t <= w1) { - w1 = t; - } - w2 -= w1; - t = h1 + y1; - if (t < 1) { - w1 = h1 = -1; - } else { - if (t <= y1) { - y2 = h1 - t; - h1 = t; - y1 = 0; - } - t = h0 - y1; - if (t < 1) { - w1 = h1 = -1; - } else { - if (t <= h1) { - h1 = t; - } - } - } - } - } - - return (w1 == -1) ? false : true; -} - } // end of namespace Kyra diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h index a6df749538..088e8b7f55 100644 --- a/engines/kyra/screen_hof.h +++ b/engines/kyra/screen_hof.h @@ -36,15 +36,12 @@ class Screen_HoF : public Screen_v2 { friend class Debugger_v2; public: Screen_HoF(KyraEngine_HoF *vm, OSystem *system); - ~Screen_HoF(); void setScreenDim(int dim); const ScreenDim *getScreenDim(int dim); // sequence player void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); - bool calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2); - void wsaFrameAnimationStep(int x1, int y1, int x2, int y2, int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim); void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage); void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false); @@ -53,8 +50,6 @@ private: static const ScreenDim _screenDimTable[]; static const int _screenDimTableCount; - - uint8 *_wsaFrameAnimBuffer; }; } // End of namespace Kyra diff --git a/engines/kyra/screen_v1.cpp b/engines/kyra/screen_lok.cpp index 9454418fd5..011c90dde9 100644 --- a/engines/kyra/screen_v1.cpp +++ b/engines/kyra/screen_lok.cpp @@ -23,36 +23,36 @@ * */ -#include "kyra/kyra_v1.h" -#include "kyra/screen_v1.h" +#include "kyra/kyra_lok.h" +#include "kyra/screen_lok.h" namespace Kyra { #define BITBLIT_RECTS 10 -Screen_v1::Screen_v1(KyraEngine_v1 *vm, OSystem *system) +Screen_LoK::Screen_LoK(KyraEngine_LoK *vm, OSystem *system) : Screen(vm, system) { _vm = vm; } -Screen_v1::~Screen_v1() { - delete [] _bitBlitRects; +Screen_LoK::~Screen_LoK() { + delete[] _bitBlitRects; for (int i = 0; i < ARRAYSIZE(_saveLoadPage); ++i) { - delete [] _saveLoadPage[i]; + delete[] _saveLoadPage[i]; _saveLoadPage[i] = 0; } for (int i = 0; i < ARRAYSIZE(_saveLoadPageOvl); ++i) { - delete [] _saveLoadPageOvl[i]; + delete[] _saveLoadPageOvl[i]; _saveLoadPageOvl[i] = 0; } - delete [] _unkPtr1; - delete [] _unkPtr2; + delete[] _unkPtr1; + delete[] _unkPtr2; } -bool Screen_v1::init() { +bool Screen_LoK::init() { if (!Screen::init()) return false; @@ -73,20 +73,20 @@ bool Screen_v1::init() { return true; } -void Screen_v1::setScreenDim(int dim) { - debugC(9, kDebugLevelScreen, "Screen_v1::setScreenDim(%d)", dim); +void Screen_LoK::setScreenDim(int dim) { + debugC(9, kDebugLevelScreen, "Screen_LoK::setScreenDim(%d)", dim); assert(dim < _screenDimTableCount); _curDim = &_screenDimTable[dim]; } -const ScreenDim *Screen_v1::getScreenDim(int dim) { - debugC(9, kDebugLevelScreen, "Screen_v1::getScreenDim(%d)", dim); +const ScreenDim *Screen_LoK::getScreenDim(int dim) { + debugC(9, kDebugLevelScreen, "Screen_LoK::getScreenDim(%d)", dim); assert(dim < _screenDimTableCount); return &_screenDimTable[dim]; } -void Screen_v1::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { - debugC(9, kDebugLevelScreen, "Screen_v1::fadeSpecialPalette(%d, %d, %d, %d)", palIndex, startIndex, size, fadeTime); +void Screen_LoK::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { + debugC(9, kDebugLevelScreen, "Screen_LoK::fadeSpecialPalette(%d, %d, %d, %d)", palIndex, startIndex, size, fadeTime); assert(_vm->palTable1()[palIndex]); assert(_currentPalette); @@ -99,8 +99,8 @@ void Screen_v1::fadeSpecialPalette(int palIndex, int startIndex, int size, int f _system->updateScreen(); } -void Screen_v1::addBitBlitRect(int x, int y, int w, int h) { - debugC(9, kDebugLevelScreen, "Screen_v1::addBitBlitRects(%d, %d, %d, %d)", x, y, w, h); +void Screen_LoK::addBitBlitRect(int x, int y, int w, int h) { + debugC(9, kDebugLevelScreen, "Screen_LoK::addBitBlitRects(%d, %d, %d, %d)", x, y, w, h); if (_bitBlitNum >= BITBLIT_RECTS) error("too many bit blit rects"); @@ -111,8 +111,8 @@ void Screen_v1::addBitBlitRect(int x, int y, int w, int h) { ++_bitBlitNum; } -void Screen_v1::bitBlitRects() { - debugC(9, kDebugLevelScreen, "Screen_v1::bitBlitRects()"); +void Screen_LoK::bitBlitRects() { + debugC(9, kDebugLevelScreen, "Screen_LoK::bitBlitRects()"); Rect *cur = _bitBlitRects; while (_bitBlitNum) { _bitBlitNum--; @@ -121,8 +121,8 @@ void Screen_v1::bitBlitRects() { } } -void Screen_v1::savePageToDisk(const char *file, int page) { - debugC(9, kDebugLevelScreen, "Screen_v1::savePageToDisk('%s', %d)", file, page); +void Screen_LoK::savePageToDisk(const char *file, int page) { + debugC(9, kDebugLevelScreen, "Screen_LoK::savePageToDisk('%s', %d)", file, page); if (!_saveLoadPage[page/2]) { _saveLoadPage[page/2] = new uint8[SCREEN_W * SCREEN_H]; assert(_saveLoadPage[page/2]); @@ -145,10 +145,10 @@ void Screen_v1::savePageToDisk(const char *file, int page) { } } -void Screen_v1::loadPageFromDisk(const char *file, int page) { - debugC(9, kDebugLevelScreen, "Screen_v1::loadPageFromDisk('%s', %d)", file, page); +void Screen_LoK::loadPageFromDisk(const char *file, int page) { + debugC(9, kDebugLevelScreen, "Screen_LoK::loadPageFromDisk('%s', %d)", file, page); copyBlockToPage(page, 0, 0, SCREEN_W, SCREEN_H, _saveLoadPage[page/2]); - delete [] _saveLoadPage[page/2]; + delete[] _saveLoadPage[page/2]; if (_saveLoadPageOvl[page/2]) { uint8 *dstPage = getOverlayPtr(page); @@ -158,24 +158,24 @@ void Screen_v1::loadPageFromDisk(const char *file, int page) { } memcpy(dstPage, _saveLoadPageOvl[page/2], SCREEN_OVL_SJIS_SIZE); - delete [] _saveLoadPageOvl[page/2]; + delete[] _saveLoadPageOvl[page/2]; _saveLoadPageOvl[page/2] = 0; } _saveLoadPage[page/2] = 0; } -void Screen_v1::deletePageFromDisk(int page) { - debugC(9, kDebugLevelScreen, "Screen_v1::deletePageFromDisk(%d)", page); - delete [] _saveLoadPage[page/2]; +void Screen_LoK::deletePageFromDisk(int page) { + debugC(9, kDebugLevelScreen, "Screen_LoK::deletePageFromDisk(%d)", page); + delete[] _saveLoadPage[page/2]; _saveLoadPage[page/2] = 0; if (_saveLoadPageOvl[page/2]) { - delete [] _saveLoadPageOvl[page/2]; + delete[] _saveLoadPageOvl[page/2]; _saveLoadPageOvl[page/2] = 0; } } -void Screen_v1::copyBackgroundBlock(int x, int page, int flag) { - debugC(9, kDebugLevelScreen, "Screen_v1::copyBackgroundBlock(%d, %d, %d)", x, page, flag); +void Screen_LoK::copyBackgroundBlock(int x, int page, int flag) { + debugC(9, kDebugLevelScreen, "Screen_LoK::copyBackgroundBlock(%d, %d, %d)", x, page, flag); if (x < 1) return; @@ -216,17 +216,17 @@ void Screen_v1::copyBackgroundBlock(int x, int page, int flag) { _curPage = oldVideoPage; } -void Screen_v1::copyBackgroundBlock2(int x) { - debugC(9, kDebugLevelScreen, "Screen_v1::copyBackgroundBlock2(%d)", x); +void Screen_LoK::copyBackgroundBlock2(int x) { + debugC(9, kDebugLevelScreen, "Screen_LoK::copyBackgroundBlock2(%d)", x); copyBackgroundBlock(x, 4, 1); } -void Screen_v1::setTextColorMap(const uint8 *cmap) { - debugC(9, kDebugLevelScreen, "Screen_v1::setTextColorMap(%p)", (const void *)cmap); +void Screen_LoK::setTextColorMap(const uint8 *cmap) { + debugC(9, kDebugLevelScreen, "Screen_LoK::setTextColorMap(%p)", (const void *)cmap); setTextColor(cmap, 0, 11); } -int Screen_v1::getRectSize(int x, int y) { +int Screen_LoK::getRectSize(int x, int y) { if (x < 1) x = 1; else if (x > 40) diff --git a/engines/kyra/screen_v1.h b/engines/kyra/screen_lok.h index 10219ae6b5..74df23a543 100644 --- a/engines/kyra/screen_v1.h +++ b/engines/kyra/screen_lok.h @@ -23,19 +23,19 @@ * */ -#ifndef KYRA_SCREEN_V1_H -#define KYRA_SCREEN_V1_H +#ifndef KYRA_SCREEN_LOK_H +#define KYRA_SCREEN_LOK_H #include "kyra/screen.h" namespace Kyra { -class KyraEngine_v1; +class KyraEngine_LoK; -class Screen_v1 : public Screen { +class Screen_LoK : public Screen { public: - Screen_v1(KyraEngine_v1 *vm, OSystem *system); - virtual ~Screen_v1(); + Screen_LoK(KyraEngine_LoK *vm, OSystem *system); + virtual ~Screen_LoK(); bool init(); @@ -59,7 +59,7 @@ public: void bitBlitRects(); protected: - KyraEngine_v1 *_vm; + KyraEngine_LoK *_vm; static const ScreenDim _screenDimTable[]; static const int _screenDimTableCount; diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index 704296c534..e26ef87bad 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -29,6 +29,15 @@ namespace Kyra { +Screen_v2::Screen_v2(KyraEngine_v1 *vm, OSystem *system) : Screen(vm, system), _wsaFrameAnimBuffer(0) { + _wsaFrameAnimBuffer = new uint8[1024]; + assert(_wsaFrameAnimBuffer); +} + +Screen_v2::~Screen_v2() { + delete[] _wsaFrameAnimBuffer; +} + uint8 *Screen_v2::generateOverlay(const uint8 *palette, uint8 *buffer, int startColor, uint16 factor) { if (!palette || !buffer) return buffer; @@ -290,6 +299,9 @@ uint8 *Screen_v2::makeShapeCopy(const uint8 *src, int index) { debugC(9, kDebugLevelScreen, "Screen_v2::makeShapeCopy(%p, %d)", (const void *)src, index); const uint8 *shape = getPtrToShape(src, index); + if (!shape) + return 0; + int size = getShapeSize(shape); uint8 *copy = new uint8[size]; @@ -333,5 +345,121 @@ void Screen_v2::setTextColorMap(const uint8 *cmap) { setTextColor(cmap, 0, 15); } +void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, + int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim) { + + if (!(w1 || h1 || w2 || h2)) + return; + + ScreenDim cdm = *getScreenDim(dim); + cdm.sx <<= 3; + cdm.w <<= 3; + + int na = 0, nb = 0, nc = w2; + + if (!calcBounds(cdm.w, cdm.h, x2, y2, w2, h2, na, nb, nc)) + return; + + const uint8 *src = getPagePtr(srcPage) + y1 * 320; + uint8 *dst = getPagePtr(dstPage) + (y2 + cdm.sy) * 320; + + int u = -1; + + do { + int t = (nb * h1) / h2; + if (t != u) { + u = t; + const uint8 *s = src + (x1 + t) * 320; + uint8 *dt = (uint8 *)_wsaFrameAnimBuffer; + + t = w2 - w1; + if (!t) { + memcpy(dt, s, w2); + } else if (t > 0) { + if (w1 == 1) { + memset(dt, *s, w2); + } else { + t = ((((((w2 - w1 + 1) & 0xffff) << 8) / w1) + 0x100) & 0xffff) << 8; + int bp = 0; + for (int i = 0; i < w1; i++) { + int cnt = (t >> 16); + bp += (t & 0xffff); + if (bp > 0xffff) { + bp -= 0xffff; + cnt++; + } + memset(dt, *s++, cnt); + dt += cnt; + } + } + } else { + if (w2 == 1) { + *dt = *s; + } else { + t = (((((w1 - w2) & 0xffff) << 8) / w2) & 0xffff) << 8; + int bp = 0; + for (int i = 0; i < w2; i++) { + *dt++ = *s++; + bp += (t & 0xffff); + if (bp > 0xffff) { + bp -= 0xffff; + s++; + } + s += (t >> 16); + } + } + } + } + memcpy(dst + x2 + cdm.sx, _wsaFrameAnimBuffer + na, w2); + dst += 320; + } while (++nb < h2); +} + +bool Screen_v2::calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2) { + x2 = 0; + y2 = 0; + w2 = w1; + + int t = x1 + w1; + if (t < 1) { + w1 = h1 = -1; + } else { + if (t <= x1) { + x2 = w1 - t; + w1 = t; + x1 = 0; + } + t = w0 - x1; + if (t < 1) { + w1 = h1 = -1; + } else { + if (t <= w1) { + w1 = t; + } + w2 -= w1; + t = h1 + y1; + if (t < 1) { + w1 = h1 = -1; + } else { + if (t <= y1) { + y2 = h1 - t; + h1 = t; + y1 = 0; + } + t = h0 - y1; + if (t < 1) { + w1 = h1 = -1; + } else { + if (t <= h1) { + h1 = t; + } + } + } + } + } + + return (w1 == -1) ? false : true; +} + } // end of namespace Kyra diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h index 5679dadf39..f624228445 100644 --- a/engines/kyra/screen_v2.h +++ b/engines/kyra/screen_v2.h @@ -33,7 +33,8 @@ namespace Kyra { class Screen_v2 : public Screen { public: - Screen_v2(KyraEngine *vm, OSystem *system) : Screen(vm, system) {} + Screen_v2(KyraEngine_v1 *vm, OSystem *system); + ~Screen_v2(); // screen page handling void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, @@ -57,13 +58,18 @@ public: // rect handling int getRectSize(int w, int h); + bool calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2); // text display void setTextColorMap(const uint8 *cmap); // layer handling virtual int getLayer(int x, int y); + + // special WSA handling + void wsaFrameAnimationStep(int x1, int y1, int x2, int y2, int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim); protected: + uint8 *_wsaFrameAnimBuffer; }; } // end of namespace Kyra diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index e9dc34e581..ef3e259cfa 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -28,12 +28,12 @@ #include "common/stream.h" #include "common/util.h" #include "common/system.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/resource.h" #include "kyra/script.h" namespace Kyra { -EMCInterpreter::EMCInterpreter(KyraEngine *vm) : _vm(vm) { +EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm) { #define COMMAND(x) { &EMCInterpreter::x, #x } static CommandEntry commandProcs[] = { // 0x00 @@ -139,9 +139,9 @@ void EMCInterpreter::unload(EMCData *data) { if (!data) return; - delete [] data->text; - delete [] data->ordr; - delete [] data->data; + delete[] data->text; + delete[] data->ordr; + delete[] data->data; data->text = 0; data->ordr = data->data = 0; diff --git a/engines/kyra/script.h b/engines/kyra/script.h index df86ec79c3..de52093f66 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -27,6 +27,7 @@ #define KYRA_SCRIPT_H #include "common/stream.h" +#include "common/array.h" #include "common/func.h" namespace Kyra { @@ -63,7 +64,7 @@ struct EMCState { #define AVTL_CHUNK 0x4C545641 class Resource; -class KyraEngine; +class KyraEngine_v1; class ScriptFileParser { public: @@ -89,7 +90,7 @@ private: class EMCInterpreter { public: - EMCInterpreter(KyraEngine *vm); + EMCInterpreter(KyraEngine_v1 *vm); bool load(const char *filename, EMCData *data, const Common::Array<const Opcode*> *opcodes); void unload(EMCData *data); @@ -101,7 +102,7 @@ public: bool run(EMCState *script); protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; int16 _parameter; typedef void (EMCInterpreter::*CommandProc)(EMCState*); diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index ff28e08960..91fbfb3e49 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -723,12 +723,6 @@ int KyraEngine_HoF::o2_loadMusicTrack(EMCState *script) { return 0; } -int KyraEngine_HoF::o2_playSoundEffect(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_playSoundEffect(%p) (%d)", (const void *)script, stackPos(0)); - snd_playSoundEffect(stackPos(0)); - return 0; -} - int KyraEngine_HoF::o2_setSceneAnimPos(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_setSceneAnimPos(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); _sceneAnims[stackPos(0)].x = stackPos(1); @@ -736,18 +730,6 @@ int KyraEngine_HoF::o2_setSceneAnimPos(EMCState *script) { return 0; } -int KyraEngine_HoF::o2_blockInRegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_blockInRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _screen->blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); - return 0; -} - -int KyraEngine_HoF::o2_blockOutRegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_blockOutRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _screen->blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); - return 0; -} - int KyraEngine_HoF::o2_setCauldronState(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_setCauldronState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); setCauldronState(stackPos(0), stackPos(1) != 0); @@ -778,7 +760,7 @@ int KyraEngine_HoF::o2_showItemString(EMCState *script) { int KyraEngine_HoF::o2_isAnySoundPlaying(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_isAnySoundPlaying(%p) ()", (const void *)script); - return _sound->voiceIsPlaying(); + return _sound->voiceIsPlaying() ? 1 : 0; } int KyraEngine_HoF::o2_setDrawNoShapeFlag(EMCState *script) { @@ -818,7 +800,7 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { _screen->fadeToBlack(0x14); sprintf(filename, "LETTER%.1d.", letter); - strcat(filename, _languageExtension[_lang]); + strcat(filename, (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _lang) ? _languageExtension[_lang] : "TXT"); uint8 *letterBuffer = _res->fileData(filename, 0); if (letterBuffer) { @@ -856,10 +838,14 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { return 0; } -int KyraEngine_HoF::o2_fillRect(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_fillRect(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - _screen->fillRect(stackPos(1), stackPos(2), stackPos(1)+stackPos(3), stackPos(2)+stackPos(4), stackPos(5), stackPos(0)); - return 0; +int KyraEngine_HoF::o2_playFireflyScore(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_playFireflyScore(%p) ()", (const void *)script); + if (_sound->getSfxType() == Sound::kAdlib || _sound->getSfxType() == Sound::kMidiMT32 || _sound->getSfxType() == Sound::kMidiGM) { + snd_playWanderScoreViaMap(86, 1); + return 1; + } else { + return 0; + } } int KyraEngine_HoF::o2_encodeShape(EMCState *script) { @@ -910,14 +896,22 @@ int KyraEngine_HoF::o2_updateSceneAnim(EMCState *script) { // Raziel^. // // We know currently of some different animations where this happens. - // - Where Marco is dangling from the flesh-eating plant (see bug #1923638 "HoF: Marco missing animation frames"). - // - After giving the ticket to the captain. He would move very fast (barely noticeable) onto the ship - // without this delay. - // - The scene after giving the sandwitch to the guards in the city. (see bug #1926838 "HoF: Animation plays too fast") - // This scene script calls o2_delay though, but since this updates the scene animation scripts again there is no delay - // for the animation. - if ((stackPos(0) == 2 && _mainCharacter.sceneId == 3) || (stackPos(0) == 3 && _mainCharacter.sceneId == 33) || - ((stackPos(0) == 1 || stackPos(0) == 2) && _mainCharacter.sceneId == 19)) + // - Where Marco is dangling from the flesh-eating plant (see bug + // #1923638 "HoF: Marco missing animation frames"). + // - After giving the ticket to the captain. He would move very fast + // (barely noticeable) onto the ship without this delay. + // - The scene after giving the sandwitch to the guards in the city. + // (see bug #1926838 "HoF: Animation plays too fast") + // This scene script calls o2_delay though, but since this updates + // the scene animation scripts again there is no delay for the + // animation. + // - When the sheriff enters the jail, either to lock you up or to throw + // away the key. (see bug #1926838 "HoF: Animation plays too fast"). + + if ((stackPos(0) == 2 && _mainCharacter.sceneId == 3) || + (stackPos(0) == 3 && _mainCharacter.sceneId == 33) || + ((stackPos(0) == 1 || stackPos(0) == 2) && _mainCharacter.sceneId == 19) || + ((stackPos(0) == 1 || stackPos(0) == 2) && _mainCharacter.sceneId == 27)) _sceneSpecialScriptsTimer[_lastProcessedSceneScript] = _system->getMillis() + _tickLength * 6; _specialSceneScriptRunFlag = false; @@ -1325,9 +1319,20 @@ int KyraEngine_HoF::o2_drawSceneShapeEx(EMCState *script) { return 0; } -int KyraEngine_HoF::o2_getBoolFromStack(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_getBoolFromStack(%p) ()", (const void *)script); - return stackPos(0) ? 1 : 0; +int KyraEngine_HoF::o2_midiSoundFadeout(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_midiSoundFadeout(%p) ()", (const void *)script); + if (!stackPos(0)) { + if ((_sound->getMusicType() == Sound::kMidiMT32 || _sound->getMusicType() == Sound::kMidiGM) && + (_sound->getSfxType() == Sound::kMidiMT32 || _sound->getSfxType() == Sound::kMidiGM)) { + _sound->beginFadeOut(); + delay(2000, true); + _lastMusicCommand = -1; + } else { + return 0; + } + } + + return 1; } int KyraEngine_HoF::o2_getSfxDriver(EMCState *script) { @@ -1539,25 +1544,25 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_removeItemFromInventory); Opcode(o2_countItemInInventory); Opcode(o2_countItemsInScene); - Opcode(o2_queryGameFlag); + Opcode(o1_queryGameFlag); // 0x28 - Opcode(o2_resetGameFlag); - Opcode(o2_setGameFlag); - Opcode(o2_setHandItem); - Opcode(o2_removeHandItem); + Opcode(o1_resetGameFlag); + Opcode(o1_setGameFlag); + Opcode(o1_setHandItem); + Opcode(o1_removeHandItem); // 0x2c - Opcode(o2_handItemSet); - Opcode(o2_hideMouse); + Opcode(o1_getMouseState); + Opcode(o1_hideMouse); Opcode(o2_addSpecialExit); - Opcode(o2_setMousePos); + Opcode(o1_setMousePos); // 0x30 - Opcode(o2_showMouse); + Opcode(o1_showMouse); OpcodeUnImpl(); Opcode(o2_wipeDownMouseItem); Opcode(o2_getElapsedSecs); // 0x34 Opcode(o2_getTimerDelay); - Opcode(o2_playSoundEffect); + Opcode(o1_playSoundEffect); Opcode(o2_delaySecs); Opcode(o2_delay); // 0x38 @@ -1601,29 +1606,29 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_setZanthiaPos); Opcode(o2_loadMusicTrack); // 0x58 - Opcode(o2_playWanderScoreViaMap); - Opcode(o2_playSoundEffect); + Opcode(o1_playWanderScoreViaMap); + Opcode(o1_playSoundEffect); Opcode(o2_setSceneAnimPos); - Opcode(o2_blockInRegion); + Opcode(o1_blockInWalkableRegion); // 0x5c - Opcode(o2_blockOutRegion); + Opcode(o1_blockOutWalkableRegion); OpcodeUnImpl(); Opcode(o2_setCauldronState); Opcode(o2_showItemString); // 0x60 - Opcode(o2_getRand); + Opcode(o1_getRand); Opcode(o2_isAnySoundPlaying); - Opcode(o2_setDeathHandler); + Opcode(o1_setDeathHandler); Opcode(o2_setDrawNoShapeFlag); // 0x64 Opcode(o2_setRunFlag); Opcode(o2_showLetter); OpcodeUnImpl(); - Opcode(o2_fillRect); + Opcode(o1_fillRect); // 0x68 OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o2_playFireflyScore); Opcode(o2_waitForConfirmationClick); // 0x6c Opcode(o2_encodeShape); @@ -1694,7 +1699,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_updateTwoSceneAnims); Opcode(o2_getRainbowRoomData); Opcode(o2_drawSceneShapeEx); - Opcode(o2_getBoolFromStack); + Opcode(o2_midiSoundFadeout); // 0xa4 Opcode(o2_getSfxDriver); Opcode(o2_getVocSupport); @@ -1716,7 +1721,7 @@ void KyraEngine_HoF::setupOpcodeTable() { // 0x00 Opcode(o2a_setAnimationShapes); Opcode(o2a_setCharacterFrame); - Opcode(o2_playSoundEffect); + Opcode(o1_playSoundEffect); Opcode(o2_fadeScenePal); // 0x04 _flags.isTalkie ? Opcode(o2a_setResetFrame) : Opcode(o2_dummy); diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp new file mode 100644 index 0000000000..efa0f8e48f --- /dev/null +++ b/engines/kyra/script_lok.cpp @@ -0,0 +1,1987 @@ +/* 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 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/endian.h" +#include "common/system.h" + +#include "kyra/kyra_lok.h" +#include "kyra/script.h" +#include "kyra/screen.h" +#include "kyra/sprites.h" +#include "kyra/wsamovie.h" +#include "kyra/animator_lok.h" +#include "kyra/text.h" +#include "kyra/timer.h" +#include "kyra/sound.h" + +namespace Kyra { +int KyraEngine_LoK::o1_magicInMouseItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + magicInMouseItem(stackPos(0), stackPos(1), -1); + return 0; +} + +int KyraEngine_LoK::o1_characterSays(EMCState *script) { + _skipFlag = false; + if (_flags.isTalkie) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_characterSays(%p) (%d, '%s', %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); + characterSays(stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); + } else { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_characterSays(%p) ('%s', %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2)); + const char *string = stackPosString(0); + + if ((_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) && _flags.lang == Common::JA_JPN) { + static const uint8 townsString1[] = { + 0x83, 0x75, 0x83, 0x89, 0x83, 0x93, 0x83, 0x83, 0x93, 0x81, + 0x41, 0x82, 0xDC, 0x82, 0xBD, 0x97, 0x88, 0x82, 0xBD, 0x82, + 0xCC, 0x82, 0xA9, 0x81, 0x48, 0x00, 0x00, 0x00 + }; + static const uint8 townsString2[] = { + 0x83, 0x75, 0x83, 0x89, 0x83, 0x93, 0x83, 0x5C, 0x83, 0x93, + 0x81, 0x41, 0x82, 0xDC, 0x82, 0xBD, 0x97, 0x88, 0x82, 0xBD, + 0x82, 0xCC, 0x82, 0xA9, 0x81, 0x48, 0x00, 0x00 + }; + + if (strncmp((const char *)townsString1, string, sizeof(townsString1)) == 0) + string = (const char *)townsString2; + } + + characterSays(-1, string, stackPos(1), stackPos(2)); + } + + return 0; +} + +int KyraEngine_LoK::o1_delay(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_delay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + if (stackPos(1)) { + warning("STUB: special o1_delay"); + // delete this after correct implementing + delayWithTicks(stackPos(0)); + } else { + delayWithTicks(stackPos(0)); + } + return 0; +} + +int KyraEngine_LoK::o1_drawSceneAnimShape(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_drawSceneAnimShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + _screen->drawShape(stackPos(4), _sprites->_sceneShapes[stackPos(0)], stackPos(1), stackPos(2), 0, (stackPos(3) != 0) ? 1 : 0); + return 0; +} + +int KyraEngine_LoK::o1_runNPCScript(EMCState *script) { + warning("STUB: o1_runNPCScript"); + return 0; +} + +int KyraEngine_LoK::o1_setSpecialExitList(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setSpecialExitList(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); + + for (int i = 0; i < 10; ++i) + _exitList[i] = stackPos(i); + _exitListPtr = _exitList; + + return 0; +} + +int KyraEngine_LoK::o1_walkPlayerToPoint(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_walkPlayerToPoint(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + + int normalTimers = stackPos(2); + if (!normalTimers) { + _timer->disable(19); + _timer->disable(14); + _timer->disable(18); + } + + int reinitScript = handleSceneChange(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + + if (!normalTimers) { + _timer->enable(19); + _timer->enable(14); + _timer->enable(18); + } + + if (reinitScript) + _emc->init(script, script->dataPtr); + + if (_sceneChangeState) { + _sceneChangeState = 0; + return 1; + } + return 0; +} + +int KyraEngine_LoK::o1_dropItemInScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_dropItemInScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + int item = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + + byte freeItem = findFreeItemInScene(_currentCharacter->sceneId); + if (freeItem != 0xFF) { + int sceneId = _currentCharacter->sceneId; + Room *room = &_roomTable[sceneId]; + room->itemsXPos[freeItem] = xpos; + room->itemsYPos[freeItem] = ypos; + room->itemsTable[freeItem] = item; + + _animator->animAddGameItem(freeItem, sceneId); + _animator->updateAllObjectShapes(); + } else { + if (item == 43) + placeItemInGenericMapScene(item, 0); + else + placeItemInGenericMapScene(item, 1); + } + return 0; +} + +int KyraEngine_LoK::o1_drawAnimShapeIntoScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_drawAnimShapeIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + _screen->hideMouse(); + _animator->restoreAllObjectBackgrounds(); + int shape = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + int flags = (stackPos(3) != 0) ? 1 : 0; + _screen->drawShape(2, _sprites->_sceneShapes[shape], xpos, ypos, 0, flags); + _screen->drawShape(0, _sprites->_sceneShapes[shape], xpos, ypos, 0, flags); + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); + _animator->flagAllObjectsForRefresh(); + _animator->updateAllObjectShapes(); + _screen->showMouse(); + return 0; +} + +int KyraEngine_LoK::o1_savePageToDisk(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_savePageToDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + _screen->savePageToDisk(stackPosString(0), stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_sceneAnimOn(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_sceneAnimOn(%p) (%d)", (const void *)script, stackPos(0)); + _sprites->_anims[stackPos(0)].play = true; + return 0; +} + +int KyraEngine_LoK::o1_sceneAnimOff(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_sceneAnimOff(%p) (%d)", (const void *)script, stackPos(0)); + _sprites->_anims[stackPos(0)].play = false; + return 0; +} + +int KyraEngine_LoK::o1_getElapsedSeconds(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getElapsedSeconds(%p) ()", (const void *)script); + return _system->getMillis() / 1000; +} + +int KyraEngine_LoK::o1_mouseIsPointer(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_mouseIsPointer(%p) ()", (const void *)script); + if (_itemInHand == -1) + return 1; + return 0; +} + +int KyraEngine_LoK::o1_runSceneAnimUntilDone(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_runSceneAnimUntilDone(%p) (%d)", (const void *)script, stackPos(0)); + _screen->hideMouse(); + _animator->restoreAllObjectBackgrounds(); + _sprites->_anims[stackPos(0)].play = true; + _animator->sprites()[stackPos(0)].active = 1; + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); + while (_sprites->_anims[stackPos(0)].play) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + delay(10); + } + _animator->restoreAllObjectBackgrounds(); + _screen->showMouse(); + return 0; +} + +int KyraEngine_LoK::o1_fadeSpecialPalette(EMCState *script) { + if (_flags.platform == Common::kPlatformAmiga) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + if (_currentCharacter->sceneId != 45) { + if (stackPos(0) == 13) { + memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3); + _screen->setScreenPalette(_screen->getPalette(0)); + } + } else { + warning("KyraEngine_LoK::o1_fadeSpecialPalette not implemented"); + } + } else { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + _screen->fadeSpecialPalette(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + } + return 0; +} + +int KyraEngine_LoK::o1_phaseInSameScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_phaseInSameScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + transcendScenes(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_setScenePhasingFlag(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setScenePhasingFlag(%p) ()", (const void *)script); + _scenePhasingFlag = 1; + return 1; +} + +int KyraEngine_LoK::o1_resetScenePhasingFlag(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_resetScenePhasingFlag(%p) ()", (const void *)script); + _scenePhasingFlag = 0; + return 0; +} + +int KyraEngine_LoK::o1_queryScenePhasingFlag(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_queryScenePhasingFlag(%p) ()", (const void *)script); + return _scenePhasingFlag; +} + +int KyraEngine_LoK::o1_sceneToDirection(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_sceneToDirection(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < _roomTableSize); + Room *curRoom = &_roomTable[stackPos(0)]; + uint16 returnValue = 0xFFFF; + switch (stackPos(1)) { + case 0: + returnValue = curRoom->northExit; + break; + + case 2: + returnValue = curRoom->eastExit; + break; + + case 4: + returnValue = curRoom->southExit; + break; + + case 6: + returnValue = curRoom->westExit; + break; + + default: + break; + } + if (returnValue == 0xFFFF) + return -1; + return returnValue; +} + +int KyraEngine_LoK::o1_setBirthstoneGem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setBirthstoneGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + int index = stackPos(0); + if (index < 4 && index >= 0) { + _birthstoneGemTable[index] = stackPos(1); + return 1; + } + return 0; +} + +int KyraEngine_LoK::o1_placeItemInGenericMapScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_placeItemInGenericMapScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + placeItemInGenericMapScene(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_setBrandonStatusBit(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); + _brandonStatusBit |= stackPos(0); + return 0; +} + +int KyraEngine_LoK::o1_delaySecs(EMCState *script) { + if (_flags.isTalkie && speechEnabled()) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_voiceDelay(%p) (%d)", (const void *)script, stackPos(0)); + if (stackPos(0) == 0) { + snd_voiceWaitForFinish(true); + } else if (stackPos(0) < 0) { + uint32 time = ABS(stackPos(0)) * _tickLength; + delay(time, true); + } + } else { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_delaySecs(%p) (%d)", (const void *)script, stackPos(0)); + if (stackPos(0) >= 0 && !_skipFlag) + delay(stackPos(0)*1000, true); + } + + _skipFlag = false; + return 0; +} + +int KyraEngine_LoK::o1_getCharacterScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getCharacterScene(%p) (%d)", (const void *)script, stackPos(0)); + return _characterList[stackPos(0)].sceneId; +} + +int KyraEngine_LoK::o1_runNPCSubscript(EMCState *script) { + warning("STUB: o1_runNPCSubscript"); + return 0; +} + +int KyraEngine_LoK::o1_magicOutMouseItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_magicOutMouseItem(%p) (%d)", (const void *)script, stackPos(0)); + magicOutMouseItem(stackPos(0), -1); + return 0; +} + +int KyraEngine_LoK::o1_internalAnimOn(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_internalAnimOn(%p) (%d)", (const void *)script, stackPos(0)); + _animator->sprites()[stackPos(0)].active = 1; + return 0; +} + +int KyraEngine_LoK::o1_forceBrandonToNormal(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_forceBrandonToNormal(%p) ()", (const void *)script); + checkAmuletAnimFlags(); + return 0; +} + +int KyraEngine_LoK::o1_poisonDeathNow(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_poisonDeathNow(%p) ()", (const void *)script); + seq_poisonDeathNow(1); + return 0; +} + +int KyraEngine_LoK::o1_setScaleMode(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setScaleMode(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int len = stackPos(0); + int setValue1 = stackPos(1); + int start2 = stackPos(2); + int setValue2 = stackPos(3); + for (int i = 0; i < len; ++i) + _scaleTable[i] = setValue1; + int temp = setValue2 - setValue1; + int temp2 = start2 - len; + for (int i = len, offset = 0; i < start2; ++i, ++offset) + _scaleTable[i] = (offset * temp) / temp2 + setValue1; + for (int i = start2; i < 145; ++i) + _scaleTable[i] = setValue2; + _scaleMode = 1; + return _scaleMode; +} + +int KyraEngine_LoK::o1_openWSAFile(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_openWSAFile(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3)); + + const char *filename = stackPosString(0); + int wsaIndex = stackPos(1); + + _movieObjects[wsaIndex]->open(filename, (stackPos(3) != 0) ? 1 : 0, 0); + assert(_movieObjects[wsaIndex]->opened()); + + return 0; +} + +int KyraEngine_LoK::o1_closeWSAFile(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_closeWSAFile(%p) (%d)", (const void *)script, stackPos(0)); + + int wsaIndex = stackPos(0); + if (_movieObjects[wsaIndex]) + _movieObjects[wsaIndex]->close(); + + return 0; +} + +int KyraEngine_LoK::o1_runWSAFromBeginningToEnd(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_runWSAFromBeginningToEnd(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + + _screen->hideMouse(); + + bool running = true; + + int xpos = stackPos(0); + int ypos = stackPos(1); + int waitTime = stackPos(2); + int wsaIndex = stackPos(3); + int worldUpdate = stackPos(4); + int wsaFrame = 0; + + _movieObjects[wsaIndex]->setX(xpos); + _movieObjects[wsaIndex]->setY(ypos); + _movieObjects[wsaIndex]->setDrawPage(0); + while (running) { + _movieObjects[wsaIndex]->displayFrame(wsaFrame++); + _animator->_updateScreen = true; + if (wsaFrame >= _movieObjects[wsaIndex]->frames()) + running = false; + + uint32 continueTime = waitTime * _tickLength + _system->getMillis(); + while (_system->getMillis() < continueTime) { + if (worldUpdate) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + } else { + _screen->updateScreen(); + } + if (continueTime - _system->getMillis() >= 10) + delay(10); + } + } + + _screen->showMouse(); + + return 0; +} + +int KyraEngine_LoK::o1_displayWSAFrame(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSAFrame(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + int frame = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + int waitTime = stackPos(3); + int wsaIndex = stackPos(4); + _screen->hideMouse(); + _movieObjects[wsaIndex]->setX(xpos); + _movieObjects[wsaIndex]->setY(ypos); + _movieObjects[wsaIndex]->setDrawPage(0); + _movieObjects[wsaIndex]->displayFrame(frame); + _animator->_updateScreen = true; + uint32 continueTime = waitTime * _tickLength + _system->getMillis(); + while (_system->getMillis() < continueTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + if (_skipFlag) + break; + + if (continueTime - _system->getMillis() >= 10) + delay(10); + } + _screen->showMouse(); + return 0; +} + +int KyraEngine_LoK::o1_enterNewScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + enterNewScene(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + return 0; +} + +int KyraEngine_LoK::o1_setSpecialEnterXAndY(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setSpecialEnterXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _brandonPosX = stackPos(0); + _brandonPosY = stackPos(1); + if (_brandonPosX + 1 == 0 && _brandonPosY + 1 == 0) + _currentCharacter->currentAnimFrame = 88; + return 0; +} + +int KyraEngine_LoK::o1_runWSAFrames(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_runWSAFrames(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + int xpos = stackPos(0); + int ypos = stackPos(1); + int delayTime = stackPos(2); + int startFrame = stackPos(3); + int endFrame = stackPos(4); + int wsaIndex = stackPos(5); + _screen->hideMouse(); + _movieObjects[wsaIndex]->setX(xpos); + _movieObjects[wsaIndex]->setY(ypos); + _movieObjects[wsaIndex]->setDrawPage(0); + for (; startFrame <= endFrame; ++startFrame) { + uint32 nextRun = _system->getMillis() + delayTime * _tickLength; + _movieObjects[wsaIndex]->displayFrame(startFrame); + _animator->_updateScreen = true; + while (_system->getMillis() < nextRun) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + if (nextRun - _system->getMillis() >= 10) + delay(10); + } + } + _screen->showMouse(); + return 0; +} + +int KyraEngine_LoK::o1_popBrandonIntoScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_popBrandonIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int changeScaleMode = stackPos(3); + int xpos = (int16)(stackPos(0) & 0xFFFC); + int ypos = (int16)(stackPos(1) & 0xFFFE); + int facing = stackPos(2); + _currentCharacter->x1 = _currentCharacter->x2 = xpos; + _currentCharacter->y1 = _currentCharacter->y2 = ypos; + _currentCharacter->facing = facing; + _currentCharacter->currentAnimFrame = 7; + int xOffset = _defaultShapeTable[0].xOffset; + int yOffset = _defaultShapeTable[0].yOffset; + int width = _defaultShapeTable[0].w << 3; + int height = _defaultShapeTable[0].h; + Animator_LoK::AnimObject *curAnim = _animator->actors(); + + if (changeScaleMode) { + curAnim->x1 = _currentCharacter->x1; + curAnim->y1 = _currentCharacter->y1; + _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1]; + _animator->_brandonScaleX = _animator->_brandonScaleY; + + int animWidth = _animator->fetchAnimWidth(curAnim->sceneAnimPtr, _animator->_brandonScaleX) >> 1; + int animHeight = _animator->fetchAnimHeight(curAnim->sceneAnimPtr, _animator->_brandonScaleY); + + animWidth = (xOffset * animWidth) / width; + animHeight = (yOffset * animHeight) / height; + + curAnim->x2 = curAnim->x1 += animWidth; + curAnim->y2 = curAnim->y1 += animHeight; + } else { + curAnim->x2 = curAnim->x1 = _currentCharacter->x1 + xOffset; + curAnim->y2 = curAnim->y1 = _currentCharacter->y1 + yOffset; + } + + int scaleModeBackup = _scaleMode; + if (changeScaleMode) + _scaleMode = 1; + + _animator->animRefreshNPC(0); + _animator->preserveAllBackgrounds(); + _animator->prepDrawAllObjects(); + _animator->copyChangedObjectsForward(0); + + _scaleMode = scaleModeBackup; + + return 0; +} + +int KyraEngine_LoK::o1_restoreAllObjectBackgrounds(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_restoreAllObjectBackgrounds(%p) (%d)", (const void *)script, stackPos(0)); + int disable = stackPos(0); + int activeBackup = 0; + if (disable) { + activeBackup = _animator->actors()->active; + _animator->actors()->active = 0; + } + _animator->restoreAllObjectBackgrounds(); + if (disable) + _animator->actors()->active = activeBackup; + return 0; +} + +int KyraEngine_LoK::o1_setCustomPaletteRange(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3); + return 0; +} + +int KyraEngine_LoK::o1_loadPageFromDisk(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_loadPageFromDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + _screen->loadPageFromDisk(stackPosString(0), stackPos(1)); + _animator->_updateScreen = true; + return 0; +} + +int KyraEngine_LoK::o1_customPrintTalkString(EMCState *script) { + if (_flags.isTalkie) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_customPrintTalkString(%p) (%d, '%s', %d, %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF); + + if (speechEnabled()) { + snd_voiceWaitForFinish(); + snd_playVoiceFile(stackPos(0)); + } + + _skipFlag = false; + if (textEnabled()) + _text->printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2); + } else { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_customPrintTalkString(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF); + _skipFlag = false; + _text->printTalkTextMessage(stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, 0, 2); + } + _screen->updateScreen(); + return 0; +} + +int KyraEngine_LoK::o1_restoreCustomPrintBackground(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_restoreCustomPrintBackground(%p) ()", (const void *)script); + _text->restoreTalkTextMessageBkgd(2, 0); + return 0; +} + +int KyraEngine_LoK::o1_getCharacterX(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getCharacterX(%p) (%d)", (const void *)script, stackPos(0)); + return _characterList[stackPos(0)].x1; +} + +int KyraEngine_LoK::o1_getCharacterY(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getCharacterY(%p) (%d)", (const void *)script, stackPos(0)); + return _characterList[stackPos(0)].y1; +} + +int KyraEngine_LoK::o1_setCharacterFacing(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCharacterFacing(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + int character = stackPos(0); + int facing = stackPos(1); + int newAnimFrame = stackPos(2); + + _animator->restoreAllObjectBackgrounds(); + if (newAnimFrame != -1) + _characterList[character].currentAnimFrame = newAnimFrame; + _characterList[character].facing = facing; + _animator->animRefreshNPC(character); + _animator->preserveAllBackgrounds(); + _animator->prepDrawAllObjects(); + _animator->copyChangedObjectsForward(0); + + return 0; +} + +int KyraEngine_LoK::o1_copyWSARegion(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_copyWSARegion(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + int xpos = stackPos(0); + int ypos = stackPos(1); + int width = stackPos(2); + int height = stackPos(3); + int srcPage = stackPos(4); + int dstPage = stackPos(5); + _screen->copyRegion(xpos, ypos, xpos, ypos, width, height, srcPage, dstPage); + _animator->_updateScreen = true; + return 0; +} + +int KyraEngine_LoK::o1_printText(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_printText(%p) ('%s', %d, %d, 0x%X, 0x%X)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + if (_flags.lang == Common::JA_JPN && stackPos(3) == 7) + _screen->printText(stackPosString(0), stackPos(1), stackPos(2), 0, 0x80); + else + _screen->printText(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + _screen->updateScreen(); + return 0; +} + +int KyraEngine_LoK::o1_loadSoundFile(EMCState *script) { + warning("STUB: o1_loadSoundFile"); + return 0; +} + +int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSAFrameOnHidPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + int frame = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + int waitTime = stackPos(3); + int wsaIndex = stackPos(4); + + _screen->hideMouse(); + uint32 continueTime = waitTime * _tickLength + _system->getMillis(); + _movieObjects[wsaIndex]->setX(xpos); + _movieObjects[wsaIndex]->setY(ypos); + _movieObjects[wsaIndex]->setDrawPage(2); + _movieObjects[wsaIndex]->displayFrame(frame); + _animator->_updateScreen = true; + while (_system->getMillis() < continueTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + if (_skipFlag) + break; + + if (continueTime - _system->getMillis() >= 10) + delay(10); + } + _screen->showMouse(); + + return 0; +} + +int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { + if (_flags.isTalkie) + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + else + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6)); + int startFrame = stackPos(0); + int endFrame = stackPos(1); + int xpos = stackPos(2); + int ypos = stackPos(3); + int waitTime = stackPos(4); + int wsaIndex = stackPos(5); + int maxTime = stackPos(6); + + if (_flags.isTalkie) { + int specialTime = stackPos(7); + if (specialTime) { + uint32 voiceTime = snd_getVoicePlayTime(); + if (voiceTime) { + int displayFrames = ABS(endFrame-startFrame)+1; + displayFrames *= maxTime; + assert(displayFrames != 0); + + bool voiceSync = false; + + if (specialTime < 0) { + voiceSync = true; + specialTime = ABS(specialTime); + } + + voiceTime *= specialTime; + voiceTime /= 100; + + if (voiceSync) { + uint32 voicePlayedTime = _sound->voicePlayedTime(_speechFile.c_str()); + if (voicePlayedTime >= voiceTime) + voiceTime = 0; + else + voiceTime -= voicePlayedTime; + } + + waitTime = voiceTime / displayFrames; + waitTime /= _tickLength; + } + } + } + + if (maxTime - 1 <= 0) + maxTime = 1; + + _movieObjects[wsaIndex]->setX(xpos); + _movieObjects[wsaIndex]->setY(ypos); + _movieObjects[wsaIndex]->setDrawPage(0); + + // Workaround for bug #1498221 "KYRA1: Glitches when meeting Zanthia" + // the original didn't do a forced screen update after displaying a wsa frame + // while we have to do it, which make brandon disappear for a short moment, + // what shouldn't happen. So we're not updating the screen for this special + // case too. + if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) { + _movieObjects[wsaIndex]->displayFrame(18); + delay(waitTime * _tickLength); + return 0; + } + + int curTime = 0; + _screen->hideMouse(); + while (curTime < maxTime) { + if (endFrame >= startFrame) { + int frame = startFrame; + while (endFrame >= frame) { + uint32 continueTime = waitTime * _tickLength + _system->getMillis(); + _movieObjects[wsaIndex]->displayFrame(frame); + if (waitTime) + _animator->_updateScreen = true; + while (_system->getMillis() < continueTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + if (_skipFlag) + break; + + if (continueTime - _system->getMillis() >= 10) + delay(10); + } + ++frame; + } + } else { + int frame = startFrame; + while (endFrame <= frame) { + uint32 continueTime = waitTime * _tickLength + _system->getMillis(); + _movieObjects[wsaIndex]->displayFrame(frame); + if (waitTime) + _animator->_updateScreen = true; + while (_system->getMillis() < continueTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + if (_skipFlag) + break; + + if (continueTime - _system->getMillis() >= 10) + delay(10); + } + --frame; + } + } + + if (_skipFlag) + break; + else + ++curTime; + } + _screen->showMouse(); + + return 0; +} + +int KyraEngine_LoK::o1_refreshCharacter(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_refreshCharacter(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int character = stackPos(0); + int animFrame = stackPos(1); + int newFacing = stackPos(2); + int updateShapes = stackPos(3); + _characterList[character].currentAnimFrame = animFrame; + if (newFacing != -1) + _characterList[character].facing = newFacing; + _animator->animRefreshNPC(character); + if (updateShapes) + _animator->updateAllObjectShapes(); + return 0; +} + +int KyraEngine_LoK::o1_internalAnimOff(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_internalAnimOff(%p) (%d)", (const void *)script, stackPos(0)); + _animator->sprites()[stackPos(0)].active = 0; + return 0; +} + +int KyraEngine_LoK::o1_changeCharactersXAndY(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_changeCharactersXAndY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + Character *ch = &_characterList[stackPos(0)]; + int16 x = stackPos(1); + int16 y = stackPos(2); + if (x != -1 && y != -1) { + x &= 0xFFFC; + y &= 0xFFFE; + } + _animator->restoreAllObjectBackgrounds(); + ch->x1 = ch->x2 = x; + ch->y1 = ch->y2 = y; + _animator->preserveAllBackgrounds(); + return 0; +} + +int KyraEngine_LoK::o1_clearSceneAnimatorBeacon(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_clearSceneAnimatorBeacon(%p) ()", (const void *)script); + _sprites->_sceneAnimatorBeaconFlag = 0; + return 0; +} + +int KyraEngine_LoK::o1_querySceneAnimatorBeacon(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_querySceneAnimatorBeacon(%p) ()", (const void *)script); + return _sprites->_sceneAnimatorBeaconFlag; +} + +int KyraEngine_LoK::o1_refreshSceneAnimator(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_refreshSceneAnimator(%p) ()", (const void *)script); + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + return 0; +} + +int KyraEngine_LoK::o1_placeItemInOffScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_placeItemInOffScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int item = stackPos(0); + int xpos = stackPos(1); + int ypos = stackPos(2); + int sceneId = stackPos(3); + + byte freeItem = findFreeItemInScene(sceneId); + if (freeItem != 0xFF) { + assert(sceneId < _roomTableSize); + Room *room = &_roomTable[sceneId]; + + room->itemsTable[freeItem] = item; + room->itemsXPos[freeItem] = xpos; + room->itemsYPos[freeItem] = ypos; + } + return 0; +} + +int KyraEngine_LoK::o1_wipeDownMouseItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_wipeDownMouseItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + _screen->hideMouse(); + wipeDownMouseItem(stackPos(1), stackPos(2)); + removeHandItem(); + _screen->showMouse(); + return 0; +} + +int KyraEngine_LoK::o1_placeCharacterInOtherScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_placeCharacterInOtherScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + int id = stackPos(0); + int sceneId = stackPos(1); + int xpos = (int16)(stackPos(2) & 0xFFFC); + int ypos = (int16)(stackPos(3) & 0xFFFE); + int facing = stackPos(4); + int animFrame = stackPos(5); + + _characterList[id].sceneId = sceneId; + _characterList[id].x1 = _characterList[id].x2 = xpos; + _characterList[id].y1 = _characterList[id].y2 = ypos; + _characterList[id].facing = facing; + _characterList[id].currentAnimFrame = animFrame; + return 0; +} + +int KyraEngine_LoK::o1_getKey(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getKey(%p) ()", (const void *)script); + waitForEvent(); + return 0; +} + +int KyraEngine_LoK::o1_specificItemInInventory(EMCState *script) { + warning("STUB: o1_specificItemInInventory"); + return 0; +} + +int KyraEngine_LoK::o1_popMobileNPCIntoScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_popMobileNPCIntoScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE)); + int character = stackPos(0); + int sceneId = stackPos(1); + int animFrame = stackPos(2); + int facing = stackPos(3); + int16 xpos = (int16)(stackPos(4) & 0xFFFC); + int8 ypos = (int16)(stackPos(5) & 0xFFFE); + Character *curChar = &_characterList[character]; + + curChar->sceneId = sceneId; + curChar->currentAnimFrame = animFrame; + curChar->facing = facing; + curChar->x1 = curChar->x2 = xpos; + curChar->y1 = curChar->y2 = ypos; + + _animator->animAddNPC(character); + _animator->updateAllObjectShapes(); + return 0; +} + +int KyraEngine_LoK::o1_mobileCharacterInScene(EMCState *script) { + warning("STUB: o1_mobileCharacterInScene"); + return 0; +} + +int KyraEngine_LoK::o1_hideMobileCharacter(EMCState *script) { + warning("STUB: o1_hideMobileCharacter"); + return 0; +} + +int KyraEngine_LoK::o1_unhideMobileCharacter(EMCState *script) { + warning("STUB: o1_unhideMobileCharacter"); + return 0; +} + +int KyraEngine_LoK::o1_setCharacterLocation(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCharacterLocation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + Character *ch = &_characterList[stackPos(0)]; + Animator_LoK::AnimObject *animObj = &_animator->actors()[stackPos(0)]; + int newScene = stackPos(1); + if (_currentCharacter->sceneId == ch->sceneId) { + if (_currentCharacter->sceneId != newScene) + animObj->active = 0; + } else if (_currentCharacter->sceneId == newScene) { + if (_currentCharacter->sceneId != ch->sceneId) + animObj->active = 1; + } + + ch->sceneId = stackPos(1); + return 0; +} + +int KyraEngine_LoK::o1_walkCharacterToPoint(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_walkCharacterToPoint(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + int character = stackPos(0); + int toX = stackPos(1); + int toY = stackPos(2); + _pathfinderFlag2 = 1; + uint32 nextFrame; + int findWayReturn = findWay(_characterList[character].x1, _characterList[character].y1, toX, toY, _movFacingTable, 150); + _pathfinderFlag2 = 0; + + if (_lastFindWayRet < findWayReturn) + _lastFindWayRet = findWayReturn; + if (findWayReturn == 0x7D00 || findWayReturn == 0) + return 0; + + int *curPos = _movFacingTable; + bool running = true; + while (running) { + bool forceContinue = false; + switch (*curPos) { + case 0: + _characterList[character].facing = 2; + break; + + case 1: + _characterList[character].facing = 1; + break; + + case 2: + _characterList[character].facing = 0; + break; + + case 3: + _characterList[character].facing = 7; + break; + + case 4: + _characterList[character].facing = 6; + break; + + case 5: + _characterList[character].facing = 5; + break; + + case 6: + _characterList[character].facing = 4; + break; + + case 7: + _characterList[character].facing = 3; + break; + + case 8: + running = 0; + break; + + default: + ++curPos; + forceContinue = true; + break; + } + + if (forceContinue || !running) + continue; + + setCharacterPosition(character, 0); + ++curPos; + + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + while (_system->getMillis() < nextFrame) { + _sprites->updateSceneAnims(); + updateMousePointer(); + _timer->update(); + _animator->updateAllObjectShapes(); + updateTextFade(); + if ((nextFrame - _system->getMillis()) >= 10) + delay(10); + } + } + return 0; +} + +int KyraEngine_LoK::o1_specialEventDisplayBrynnsNote(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_specialEventDisplayBrynnsNote(%p) ()", (const void *)script); + _screen->hideMouse(); + _screen->savePageToDisk("HIDPAGE.TMP", 2); + _screen->savePageToDisk("SEENPAGE.TMP", 0); + if (_flags.isTalkie) { + if (_flags.lang == Common::EN_ANY || _flags.lang == Common::IT_ITA) + _screen->loadBitmap("NOTEENG.CPS", 3, 3, 0); + else if (_flags.lang == Common::FR_FRA) + _screen->loadBitmap("NOTEFRE.CPS", 3, 3, 0); + else if (_flags.lang == Common::DE_DEU) + _screen->loadBitmap("NOTEGER.CPS", 3, 3, 0); + } else { + _screen->loadBitmap("NOTE.CPS", 3, 3, 0); + } + _screen->copyRegion(63, 8, 63, 8, 194, 128, 2, 0); + _screen->updateScreen(); + _screen->showMouse(); + _screen->setFont(Screen::FID_6_FNT); + return 0; +} + +int KyraEngine_LoK::o1_specialEventRemoveBrynnsNote(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_specialEventRemoveBrynnsNote(%p) ()", (const void *)script); + _screen->hideMouse(); + _screen->loadPageFromDisk("SEENPAGE.TMP", 0); + _screen->loadPageFromDisk("HIDPAGE.TMP", 2); + _screen->updateScreen(); + _screen->showMouse(); + _screen->setFont(Screen::FID_8_FNT); + return 0; +} + +int KyraEngine_LoK::o1_setLogicPage(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setLogicPage(%p) (%d)", (const void *)script, stackPos(0)); + _screen->_curPage = stackPos(0); + return stackPos(0); +} + +int KyraEngine_LoK::o1_fatPrint(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fatPrint(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + + // Workaround for bug #1582672 ("KYRA1: Text crippled and drawn wrong") + // I'm not sure how the original handles this, since it seems to call + // printText also, maybe it fails somewhere inside... + // TODO: fix the reason for this workaround + if (_currentRoom == 117) + return 0; + _text->printText(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + return 0; +} + +int KyraEngine_LoK::o1_preserveAllObjectBackgrounds(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_preserveAllObjectBackgrounds(%p) ()", (const void *)script); + _animator->preserveAllBackgrounds(); + return 0; +} + +int KyraEngine_LoK::o1_updateSceneAnimations(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_updateSceneAnimations(%p) (%d)", (const void *)script, stackPos(0)); + int times = stackPos(0); + while (times--) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + } + return 0; +} + +int KyraEngine_LoK::o1_sceneAnimationActive(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_sceneAnimationActive(%p) (%d)", (const void *)script, stackPos(0)); + return _sprites->_anims[stackPos(0)].play; +} + +int KyraEngine_LoK::o1_setCharacterMovementDelay(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCharacterMovementDelay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _timer->setDelay(stackPos(0)+5, stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_getCharacterFacing(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getCharacterFacing(%p) (%d)", (const void *)script, stackPos(0)); + return _characterList[stackPos(0)].facing; +} + +int KyraEngine_LoK::o1_bkgdScrollSceneAndMasksRight(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_bkgdScrollSceneAndMasksRight(%p) (%d)", (const void *)script, stackPos(0)); + _screen->copyBackgroundBlock(stackPos(0), 2, 0); + _screen->copyBackgroundBlock2(stackPos(0)); + // update the whole screen + _screen->copyRegion(7, 7, 7, 7, 305, 129, 3, 0); + // Don't do a screen update here, see bug #1910180 "KYRA1: Screen 'flash'" + // it would cause to draw the screen with a wrong palette and thus look + // strange for the user. Since this opcode should be just called on scene + // initialization anyway, there should be no problem with not updating the + // screen right now. + return 0; +} + +int KyraEngine_LoK::o1_dispelMagicAnimation(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_dispelMagicAnimation(%p) ()", (const void *)script); + seq_dispelMagicAnimation(); + return 0; +} + +int KyraEngine_LoK::o1_findBrightestFireberry(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_findBrightestFireberry(%p) ()", (const void *)script); + if (_currentCharacter->sceneId >= 187 && _currentCharacter->sceneId <= 198) + return 29; + + if (_currentCharacter->sceneId == 133 || _currentCharacter->sceneId == 137 || + _currentCharacter->sceneId == 165 || _currentCharacter->sceneId == 173) + return 29; + + if (_itemInHand == 28) + return 28; + + int brightestFireberry = 107; + if (_itemInHand >= 29 && _itemInHand <= 33) + brightestFireberry = _itemInHand; + for (int i = 0; i < 10; ++i) { + uint8 item = _currentCharacter->inventoryItems[i]; + if (item == 0xFF) + continue; + if (item == 28) + return 28; + if (item >= 29 && item <= 33) { + if (item < brightestFireberry) + brightestFireberry = item; + } + } + assert(_currentCharacter->sceneId < _roomTableSize); + Room *curRoom = &_roomTable[_currentCharacter->sceneId]; + for (int i = 0; i < 12; ++i) { + uint8 item = curRoom->itemsTable[i]; + if (item == 0xFF) + continue; + if (item == 28) + return 28; + if (item >= 29 && item <= 33) { + if (item < brightestFireberry) + brightestFireberry = item; + } + } + if (brightestFireberry == 107) + return -1; + return brightestFireberry; +} + +int KyraEngine_LoK::o1_setFireberryGlowPalette(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0)); + int palIndex = 0; + switch (stackPos(0)) { + case 0x1E: + palIndex = 9; + break; + + case 0x1F: + palIndex = 10; + break; + + case 0x20: + palIndex = 11; + break; + + case 0x21: + case -1: + palIndex = 12; + break; + + default: + palIndex = 8; + break; + } + if (_brandonStatusBit & 2) { + if (_currentCharacter->sceneId != 133 && _currentCharacter->sceneId != 137 && + _currentCharacter->sceneId != 165 && _currentCharacter->sceneId != 173 && + (_currentCharacter->sceneId < 187 || _currentCharacter->sceneId > 198)) { + palIndex = 14; + } + } + const uint8 *palette = _specialPalettes[palIndex]; + memcpy(_screen->getPalette(1) + 684, palette, 44); + return 0; +} + +int KyraEngine_LoK::o1_drinkPotionAnimation(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_drinkPotionAnimation(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + seq_playDrinkPotionAnim(stackPos(0), stackPos(1), stackPos(2)); + return 0; +} + +int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_makeAmuletAppear(%p) ()", (const void *)script); + WSAMovie_v1 amulet(this); + amulet.open("AMULET.WSA", 1, 0); + amulet.setX(224); + amulet.setY(152); + amulet.setDrawPage(0); + if (amulet.opened()) { + assert(_amuleteAnim); + _screen->hideMouse(); + snd_playSoundEffect(0x70); + uint32 nextTime = 0; + for (int i = 0; _amuleteAnim[i] != 0xFF; ++i) { + nextTime = _system->getMillis() + 5 * _tickLength; + + uint8 code = _amuleteAnim[i]; + if (code == 3 || code == 7) + snd_playSoundEffect(0x71); + + if (code == 5) + snd_playSoundEffect(0x72); + + if (code == 14) + snd_playSoundEffect(0x73); + + amulet.displayFrame(code); + _animator->_updateScreen = true; + + while (_system->getMillis() < nextTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + if (nextTime - _system->getMillis() >= 10) + delay(10); + } + } + _screen->showMouse(); + } + setGameFlag(0x2D); + return 0; +} + +int KyraEngine_LoK::o1_drawItemShapeIntoScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_drawItemShapeIntoScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + int item = stackPos(0); + int x = stackPos(1); + int y = stackPos(2); + int flags = stackPos(3); + int onlyHidPage = stackPos(4); + + if (flags) + flags = 1; + + if (onlyHidPage) { + _screen->drawShape(2, _shapes[216+item], x, y, 0, flags); + } else { + _screen->hideMouse(); + _animator->restoreAllObjectBackgrounds(); + _screen->drawShape(2, _shapes[216+item], x, y, 0, flags); + _screen->drawShape(0, _shapes[216+item], x, y, 0, flags); + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); + _animator->flagAllObjectsForRefresh(); + _animator->updateAllObjectShapes(); + _screen->showMouse(); + } + return 0; +} + +int KyraEngine_LoK::o1_setCharacterCurrentFrame(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCharacterCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _characterList[stackPos(0)].currentAnimFrame = stackPos(1); + return 0; +} + +int KyraEngine_LoK::o1_waitForConfirmationMouseClick(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_waitForConfirmationMouseClick(%p) ()", (const void *)script); + // if (mouseEnabled) { + while (!_mousePressFlag) { + updateMousePointer(); + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + delay(10); + } + + while (_mousePressFlag) { + updateMousePointer(); + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + delay(10); + } + // } + _gui->processButtonList(_buttonList, 0, 0); + _skipFlag = false; + Common::Point mouse = getMousePos(); + script->regs[1] = mouse.x; + script->regs[2] = mouse.y; + return 0; +} + +int KyraEngine_LoK::o1_pageFlip(EMCState *script) { + warning("STUB: o1_pageFlip"); + return 0; +} + +int KyraEngine_LoK::o1_setSceneFile(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setSceneFile(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + setSceneFile(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_getItemInMarbleVase(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getItemInMarbleVase(%p) ()", (const void *)script); + return _marbleVaseItem; +} + +int KyraEngine_LoK::o1_setItemInMarbleVase(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setItemInMarbleVase(%p) (%d)", (const void *)script, stackPos(0)); + _marbleVaseItem = stackPos(0); + return 0; +} + +int KyraEngine_LoK::o1_addItemToInventory(EMCState *script) { + warning("STUB: o1_addItemToInventory"); + return 0; +} + +int KyraEngine_LoK::o1_intPrint(EMCState *script) { + warning("STUB: o1_intPrint"); + return 0; +} + +int KyraEngine_LoK::o1_shakeScreen(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_shakeScreen(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + int waitTicks = stackPos(1); + int times = stackPos(0); + + for (int i = 0; i < times; ++i) { + _screen->shakeScreen(1); + delay(waitTicks * _tickLength); + } + + return 0; +} + +int KyraEngine_LoK::o1_createAmuletJewel(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_createAmuletJewel(%p) (%d)", (const void *)script, stackPos(0)); + seq_createAmuletJewel(stackPos(0), 0, 0, 0); + return 0; +} + +int KyraEngine_LoK::o1_setSceneAnimCurrXY(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setSceneAnimCurrXY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + _sprites->_anims[stackPos(0)].x = stackPos(1); + _sprites->_anims[stackPos(0)].y = stackPos(2); + return 0; +} + +int KyraEngine_LoK::o1_poisonBrandonAndRemaps(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_poisonBrandonAndRemaps(%p) ()", (const void *)script); + setBrandonPoisonFlags(1); + return 0; +} + +int KyraEngine_LoK::o1_fillFlaskWithWater(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fillFlaskWithWater(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + seq_fillFlaskWithWater(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_getCharacterMovementDelay(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getCharacterMovementDelay(%p) (%d)", (const void *)script, stackPos(0)); + return _timer->getDelay(stackPos(0)+5); +} + +int KyraEngine_LoK::o1_getBirthstoneGem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getBirthstoneGem(%p) (%d)", (const void *)script, stackPos(0)); + if (stackPos(0) < 4) + return _birthstoneGemTable[stackPos(0)]; + return 0; +} + +int KyraEngine_LoK::o1_queryBrandonStatusBit(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_queryBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); + if (_brandonStatusBit & stackPos(0)) + return 1; + return 0; +} + +int KyraEngine_LoK::o1_playFluteAnimation(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_playFluteAnimation(%p) ()", (const void *)script); + seq_playFluteAnimation(); + return 0; +} + +int KyraEngine_LoK::o1_playWinterScrollSequence(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_playWinterScrollSequence(%p) (%d)", (const void *)script, stackPos(0)); + if (!stackPos(0)) + seq_winterScroll2(); + else + seq_winterScroll1(); + return 0; +} + +int KyraEngine_LoK::o1_getIdolGem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getIdolGem(%p) (%d)", (const void *)script, stackPos(0)); + return _idolGemsTable[stackPos(0)]; +} + +int KyraEngine_LoK::o1_setIdolGem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setIdolGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _idolGemsTable[stackPos(0)] = stackPos(1); + return 0; +} + +int KyraEngine_LoK::o1_totalItemsInScene(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_totalItemsInScene(%p) (%d)", (const void *)script, stackPos(0)); + return countItemsInScene(stackPos(0)); +} + +int KyraEngine_LoK::o1_restoreBrandonsMovementDelay(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_restoreBrandonsMovementDelay(%p) ()", (const void *)script); + setWalkspeed(_configWalkspeed); + return 0; +} + +int KyraEngine_LoK::o1_setEntranceMouseCursorTrack(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setEntranceMouseCursorTrack(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + _entranceMouseCursorTracks[0] = stackPos(0); + _entranceMouseCursorTracks[1] = stackPos(1); + _entranceMouseCursorTracks[2] = stackPos(0) + stackPos(2) - 1; + _entranceMouseCursorTracks[3] = stackPos(1) + stackPos(3) - 1; + _entranceMouseCursorTracks[4] = stackPos(4); + return 0; +} + +int KyraEngine_LoK::o1_itemAppearsOnGround(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_itemAppearsOnGround(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + processItemDrop(_currentCharacter->sceneId, stackPos(0), stackPos(1), stackPos(2), 2, 0); + return 0; +} + +int KyraEngine_LoK::o1_setNoDrawShapesFlag(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setNoDrawShapesFlag(%p) (%d)", (const void *)script, stackPos(0)); + _animator->_noDrawShapesFlag = stackPos(0); + return 0; +} + +int KyraEngine_LoK::o1_fadeEntirePalette(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + int cmd = stackPos(0); + uint8 *fadePal = 0; + + if (_flags.platform == Common::kPlatformAmiga) { + if (cmd == 0) { + fadePal = _screen->getPalette(2); + memset(fadePal, 0, 32*3); + memcpy(_screen->getPalette(4), _screen->getPalette(0), 32*3); + } else if (cmd == 1) { + fadePal = _screen->getPalette(0); + memcpy(_screen->getPalette(0), _screen->getPalette(4), 32*3); + } else if (cmd == 2) { + fadePal = _screen->getPalette(0); + memset(_screen->getPalette(2), 0, 32*3); + } + } else { + if (cmd == 0) { + fadePal = _screen->getPalette(2); + uint8 *screenPal = _screen->getPalette(0); + uint8 *backUpPal = _screen->getPalette(3); + + memcpy(backUpPal, screenPal, sizeof(uint8)*768); + memset(fadePal, 0, sizeof(uint8)*768); + } else if (cmd == 1) { + //fadePal = _screen->getPalette(3); + warning("unimplemented o1_fadeEntirePalette function"); + return 0; + } else if (cmd == 2) { + memset(_screen->getPalette(2), 0, 768); + memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + fadePal = _screen->getPalette(0); + } + } + + _screen->fadePalette(fadePal, stackPos(1)); + return 0; +} + +int KyraEngine_LoK::o1_itemOnGroundHere(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_itemOnGroundHere(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < _roomTableSize); + Room *curRoom = &_roomTable[stackPos(0)]; + for (int i = 0; i < 12; ++i) { + if (curRoom->itemsTable[i] == stackPos(1)) + return 1; + } + return 0; +} + +int KyraEngine_LoK::o1_queryCauldronState(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_queryCauldronState(%p) ()", (const void *)script); + return _cauldronState; +} + +int KyraEngine_LoK::o1_setCauldronState(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCauldronState(%p) (%d)", (const void *)script, stackPos(0)); + _cauldronState = stackPos(0); + return _cauldronState; +} + +int KyraEngine_LoK::o1_queryCrystalState(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_queryCrystalState(%p) (%d)", (const void *)script, stackPos(0)); + if (!stackPos(0)) + return _crystalState[0]; + else if (stackPos(0) == 1) + return _crystalState[1]; + return -1; +} + +int KyraEngine_LoK::o1_setCrystalState(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCrystalState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + if (!stackPos(0)) + _crystalState[0] = stackPos(1); + else if (stackPos(0) == 1) + _crystalState[1] = stackPos(1); + return stackPos(1); +} + +int KyraEngine_LoK::o1_setPaletteRange(EMCState *script) { + warning("STUB: o1_setPaletteRange"); + return 0; +} + +int KyraEngine_LoK::o1_shrinkBrandonDown(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_shrinkBrandonDown(%p) (%d)", (const void *)script, stackPos(0)); + int delayTime = stackPos(0); + checkAmuletAnimFlags(); + int scaleValue = _scaleTable[_currentCharacter->y1]; + int scale = 0; + + if (_scaleMode) + scale = scaleValue; + else + scale = 256; + + int scaleModeBackUp = _scaleMode; + _scaleMode = 1; + int scaleEnd = scale >> 1; + for (; scaleEnd <= scale; --scale) { + _scaleTable[_currentCharacter->y1] = scale; + _animator->animRefreshNPC(0); + delayWithTicks(1); + } + delayWithTicks(delayTime); // XXX + _scaleTable[_currentCharacter->y1] = scaleValue; + _scaleMode = scaleModeBackUp; + return 0; +} + +int KyraEngine_LoK::o1_growBrandonUp(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_growBrandonUp(%p) ()", (const void *)script); + int scaleValue = _scaleTable[_currentCharacter->y1]; + int scale = 0; + if (_scaleMode) + scale = scaleValue; + else + scale = 256; + + int scaleModeBackUp = _scaleMode; + _scaleMode = 1; + for (int curScale = scale >> 1; curScale <= scale; ++curScale) { + _scaleTable[_currentCharacter->y1] = curScale; + _animator->animRefreshNPC(0); + delayWithTicks(1); + } + _scaleTable[_currentCharacter->y1] = scaleValue; + _scaleMode = scaleModeBackUp; + return 0; +} + +int KyraEngine_LoK::o1_setBrandonScaleXAndY(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setBrandonScaleXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _animator->_brandonScaleX = stackPos(0); + _animator->_brandonScaleY = stackPos(1); + return 0; +} + +int KyraEngine_LoK::o1_resetScaleMode(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_resetScaleMode(%p) ()", (const void *)script); + _scaleMode = 0; + return 0; +} + +int KyraEngine_LoK::o1_getScaleDepthTableValue(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getScaleDepthTableValue(%p) (%d)", (const void *)script, stackPos(0)); + assert(stackPos(0) < ARRAYSIZE(_scaleTable)); + return _scaleTable[stackPos(0)]; +} + +int KyraEngine_LoK::o1_setScaleDepthTableValue(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setScaleDepthTableValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < ARRAYSIZE(_scaleTable)); + _scaleTable[stackPos(0)] = stackPos(1); + return stackPos(1); +} + +int KyraEngine_LoK::o1_message(EMCState *script) { + if (_flags.isTalkie) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_message(%p) (%d, '%s', %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2)); + drawSentenceCommand(stackPosString(1), stackPos(2)); + } else { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_message(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + drawSentenceCommand(stackPosString(0), stackPos(1)); + } + + return 0; +} + +int KyraEngine_LoK::o1_checkClickOnNPC(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_checkClickOnNPC(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + return checkForNPCScriptRun(stackPos(0), stackPos(1)); +} + +int KyraEngine_LoK::o1_getFoyerItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getFoyerItem(%p) (%d)", (const void *)script, stackPos(0)); + assert(stackPos(0) < ARRAYSIZE(_foyerItemTable)); + return _foyerItemTable[stackPos(0)]; +} + +int KyraEngine_LoK::o1_setFoyerItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setFoyerItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < ARRAYSIZE(_foyerItemTable)); + _foyerItemTable[stackPos(0)] = stackPos(1); + return stackPos(1); +} + +int KyraEngine_LoK::o1_setNoItemDropRegion(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setNoItemDropRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + addToNoDropRects(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + return 0; +} + +int KyraEngine_LoK::o1_walkMalcolmOn(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_walkMalcolmOn(%p) ()", (const void *)script); + if (!_malcolmFlag) + _malcolmFlag = 1; + return 0; +} + +int KyraEngine_LoK::o1_passiveProtection(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_passiveProtection(%p) ()", (const void *)script); + return 1; +} + +int KyraEngine_LoK::o1_setPlayingLoop(EMCState *script) { + warning("STUB: o1_setPlayingLoop"); + return 0; +} + +int KyraEngine_LoK::o1_brandonToStoneSequence(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_brandonToStoneSequence(%p) ()", (const void *)script); + seq_brandonToStone(); + return 0; +} + +int KyraEngine_LoK::o1_brandonHealingSequence(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_brandonHealingSequence(%p) ()", (const void *)script); + seq_brandonHealing(); + return 0; +} + +int KyraEngine_LoK::o1_protectCommandLine(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_protectCommandLine(%p) (%d)", (const void *)script, stackPos(0)); + return stackPos(0); +} + +int KyraEngine_LoK::o1_pauseMusicSeconds(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_pauseMusicSeconds(%p) ()", (const void *)script); + // if music disabled + // return + delay(stackPos(0)*1000, true); + return 0; +} + +int KyraEngine_LoK::o1_resetMaskRegion(EMCState *script) { + warning("STUB: o1_resetMaskRegion"); + return 0; +} + +int KyraEngine_LoK::o1_setPaletteChangeFlag(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setPaletteChangeFlag(%p) (%d)", (const void *)script, stackPos(0)); + _paletteChanged = stackPos(0); + return _paletteChanged; +} + +int KyraEngine_LoK::o1_vocUnload(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_vocUnload(%p) ()", (const void *)script); + // this should unload all voc files (not needed) + return 0; +} + +int KyraEngine_LoK::o1_vocLoad(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_vocLoad(%p) (%d)", (const void *)script, stackPos(0)); + // this should load the specified voc file (not needed) + return 0; +} + +int KyraEngine_LoK::o1_dummy(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_dummy(%p) ()", (const void *)script); + return 0; +} + +#pragma mark - + +typedef Common::Functor1Mem<EMCState*, int, KyraEngine_LoK> OpcodeV1; +#define SetOpcodeTable(x) table = &x; +#define Opcode(x) table->push_back(new OpcodeV1(this, &KyraEngine_LoK::x)) +void KyraEngine_LoK::setupOpcodeTable() { + Common::Array<const Opcode *> *table = 0; + + SetOpcodeTable(_opcodes); + // 0x00 + Opcode(o1_magicInMouseItem); + Opcode(o1_characterSays); + Opcode(o1_delay); + Opcode(o1_drawSceneAnimShape); + // 0x04 + Opcode(o1_queryGameFlag); + Opcode(o1_setGameFlag); + Opcode(o1_resetGameFlag); + Opcode(o1_runNPCScript); + // 0x08 + Opcode(o1_setSpecialExitList); + Opcode(o1_blockInWalkableRegion); + Opcode(o1_blockOutWalkableRegion); + Opcode(o1_walkPlayerToPoint); + // 0x0c + Opcode(o1_dropItemInScene); + Opcode(o1_drawAnimShapeIntoScene); + Opcode(o1_setHandItem); + Opcode(o1_savePageToDisk); + // 0x10 + Opcode(o1_sceneAnimOn); + Opcode(o1_sceneAnimOff); + Opcode(o1_getElapsedSeconds); + Opcode(o1_mouseIsPointer); + // 0x14 + Opcode(o1_removeHandItem); + Opcode(o1_runSceneAnimUntilDone); + Opcode(o1_fadeSpecialPalette); + Opcode(o1_playSoundEffect); + // 0x18 + Opcode(o1_playWanderScoreViaMap); + Opcode(o1_phaseInSameScene); + Opcode(o1_setScenePhasingFlag); + Opcode(o1_resetScenePhasingFlag); + // 0x1c + Opcode(o1_queryScenePhasingFlag); + Opcode(o1_sceneToDirection); + Opcode(o1_setBirthstoneGem); + Opcode(o1_placeItemInGenericMapScene); + // 0x20 + Opcode(o1_setBrandonStatusBit); + Opcode(o1_delaySecs); + Opcode(o1_getCharacterScene); + Opcode(o1_runNPCSubscript); + // 0x24 + Opcode(o1_magicOutMouseItem); + Opcode(o1_internalAnimOn); + Opcode(o1_forceBrandonToNormal); + Opcode(o1_poisonDeathNow); + // 0x28 + Opcode(o1_setScaleMode); + Opcode(o1_openWSAFile); + Opcode(o1_closeWSAFile); + Opcode(o1_runWSAFromBeginningToEnd); + // 0x2c + Opcode(o1_displayWSAFrame); + Opcode(o1_enterNewScene); + Opcode(o1_setSpecialEnterXAndY); + Opcode(o1_runWSAFrames); + // 0x30 + Opcode(o1_popBrandonIntoScene); + Opcode(o1_restoreAllObjectBackgrounds); + Opcode(o1_setCustomPaletteRange); + Opcode(o1_loadPageFromDisk); + // 0x34 + Opcode(o1_customPrintTalkString); + Opcode(o1_restoreCustomPrintBackground); + Opcode(o1_hideMouse); + Opcode(o1_showMouse); + // 0x38 + Opcode(o1_getCharacterX); + Opcode(o1_getCharacterY); + Opcode(o1_setCharacterFacing); + Opcode(o1_copyWSARegion); + // 0x3c + Opcode(o1_printText); + Opcode(o1_getRand); + Opcode(o1_loadSoundFile); + Opcode(o1_displayWSAFrameOnHidPage); + // 0x40 + Opcode(o1_displayWSASequentialFrames); + Opcode(o1_refreshCharacter); + Opcode(o1_internalAnimOff); + Opcode(o1_changeCharactersXAndY); + // 0x44 + Opcode(o1_clearSceneAnimatorBeacon); + Opcode(o1_querySceneAnimatorBeacon); + Opcode(o1_refreshSceneAnimator); + Opcode(o1_placeItemInOffScene); + // 0x48 + Opcode(o1_wipeDownMouseItem); + Opcode(o1_placeCharacterInOtherScene); + Opcode(o1_getKey); + Opcode(o1_specificItemInInventory); + // 0x4c + Opcode(o1_popMobileNPCIntoScene); + Opcode(o1_mobileCharacterInScene); + Opcode(o1_hideMobileCharacter); + Opcode(o1_unhideMobileCharacter); + // 0x50 + Opcode(o1_setCharacterLocation); + Opcode(o1_walkCharacterToPoint); + Opcode(o1_specialEventDisplayBrynnsNote); + Opcode(o1_specialEventRemoveBrynnsNote); + // 0x54 + Opcode(o1_setLogicPage); + Opcode(o1_fatPrint); + Opcode(o1_preserveAllObjectBackgrounds); + Opcode(o1_updateSceneAnimations); + // 0x58 + Opcode(o1_sceneAnimationActive); + Opcode(o1_setCharacterMovementDelay); + Opcode(o1_getCharacterFacing); + Opcode(o1_bkgdScrollSceneAndMasksRight); + // 0x5c + Opcode(o1_dispelMagicAnimation); + Opcode(o1_findBrightestFireberry); + Opcode(o1_setFireberryGlowPalette); + Opcode(o1_setDeathHandler); + // 0x60 + Opcode(o1_drinkPotionAnimation); + Opcode(o1_makeAmuletAppear); + Opcode(o1_drawItemShapeIntoScene); + Opcode(o1_setCharacterCurrentFrame); + // 0x64 + Opcode(o1_waitForConfirmationMouseClick); + Opcode(o1_pageFlip); + Opcode(o1_setSceneFile); + Opcode(o1_getItemInMarbleVase); + // 0x68 + Opcode(o1_setItemInMarbleVase); + Opcode(o1_addItemToInventory); + Opcode(o1_intPrint); + Opcode(o1_shakeScreen); + // 0x6c + Opcode(o1_createAmuletJewel); + Opcode(o1_setSceneAnimCurrXY); + Opcode(o1_poisonBrandonAndRemaps); + Opcode(o1_fillFlaskWithWater); + // 0x70 + Opcode(o1_getCharacterMovementDelay); + Opcode(o1_getBirthstoneGem); + Opcode(o1_queryBrandonStatusBit); + Opcode(o1_playFluteAnimation); + // 0x74 + Opcode(o1_playWinterScrollSequence); + Opcode(o1_getIdolGem); + Opcode(o1_setIdolGem); + Opcode(o1_totalItemsInScene); + // 0x78 + Opcode(o1_restoreBrandonsMovementDelay); + Opcode(o1_setMousePos); + Opcode(o1_getMouseState); + Opcode(o1_setEntranceMouseCursorTrack); + // 0x7c + Opcode(o1_itemAppearsOnGround); + Opcode(o1_setNoDrawShapesFlag); + Opcode(o1_fadeEntirePalette); + Opcode(o1_itemOnGroundHere); + // 0x80 + Opcode(o1_queryCauldronState); + Opcode(o1_setCauldronState); + Opcode(o1_queryCrystalState); + Opcode(o1_setCrystalState); + // 0x84 + Opcode(o1_setPaletteRange); + Opcode(o1_shrinkBrandonDown); + Opcode(o1_growBrandonUp); + Opcode(o1_setBrandonScaleXAndY); + // 0x88 + Opcode(o1_resetScaleMode); + Opcode(o1_getScaleDepthTableValue); + Opcode(o1_setScaleDepthTableValue); + Opcode(o1_message); + // 0x8c + Opcode(o1_checkClickOnNPC); + Opcode(o1_getFoyerItem); + Opcode(o1_setFoyerItem); + Opcode(o1_setNoItemDropRegion); + // 0x90 + Opcode(o1_walkMalcolmOn); + Opcode(o1_passiveProtection); + Opcode(o1_setPlayingLoop); + Opcode(o1_brandonToStoneSequence); + // 0x94 + Opcode(o1_brandonHealingSequence); + Opcode(o1_protectCommandLine); + Opcode(o1_pauseMusicSeconds); + Opcode(o1_resetMaskRegion); + // 0x98 + Opcode(o1_setPaletteChangeFlag); + Opcode(o1_fillRect); + Opcode(o1_vocUnload); + Opcode(o1_vocLoad); + // 0x9c + Opcode(o1_dummy); +} +#undef Opcode + +} // end of namespace Kyra + diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 8746ec83d7..9a059ead2a 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -134,6 +134,12 @@ int KyraEngine_MR::o3_hideBadConscience(EMCState *script) { return 0; } +int KyraEngine_MR::o3_showAlbum(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_showAlbum(%p) ()", (const void *)script); + showAlbum(); + return 0; +} + int KyraEngine_MR::o3_setInventorySlot(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_setInventorySlot(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); const int slot = MAX<int16>(0, MIN<int16>(10, stackPos(0))); @@ -551,7 +557,7 @@ int KyraEngine_MR::o3_updateConversations(EMCState *script) { convs[0] = 0; convs[1] = 4; convs[2] = 0; - convs[4] = 1; + convs[3] = 1; break; case 10: @@ -588,6 +594,13 @@ int KyraEngine_MR::o3_updateConversations(EMCState *script) { return 1; } +int KyraEngine_MR::o3_removeItemSlot(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_removeItemSlot(%p) (%d)", (const void *)script, stackPos(0)); + deleteItemAnimEntry(stackPos(0)); + _itemList[stackPos(0)].id = 0xFFFF; + return 1; +} + int KyraEngine_MR::o3_setSceneDim(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_setSceneDim(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _sceneMinX = stackPos(0); @@ -798,8 +811,8 @@ int KyraEngine_MR::o3_daggerWarning(EMCState *script) { return selection; } -int KyraEngine_MR::o3_blockOutRegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_blockOutRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); +int KyraEngine_MR::o3_blockOutWalkableRegion(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); const int x1 = stackPos(0); int y1 = stackPos(1); const int x2 = stackPos(2); @@ -1169,7 +1182,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_hideBadConscience); // 0x18 OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_showAlbum); Opcode(o3_setInventorySlot); Opcode(o3_getInventorySlot); // 0x1c @@ -1186,19 +1199,19 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_removeInventoryItemInstances); Opcode(o3_countInventoryItemInstances); Opcode(o3_npcChatSequence); - Opcode(o2_queryGameFlag); + Opcode(o1_queryGameFlag); // 0x28 - Opcode(o2_resetGameFlag); - Opcode(o2_setGameFlag); - Opcode(o2_setHandItem); - Opcode(o2_removeHandItem); + Opcode(o1_resetGameFlag); + Opcode(o1_setGameFlag); + Opcode(o1_setHandItem); + Opcode(o1_removeHandItem); // 0x2c - Opcode(o2_handItemSet); - Opcode(o2_hideMouse); + Opcode(o1_getMouseState); + Opcode(o1_hideMouse); Opcode(o2_addSpecialExit); - Opcode(o2_setMousePos); + Opcode(o1_setMousePos); // 0x30 - Opcode(o2_showMouse); + Opcode(o1_showMouse); Opcode(o3_badConscienceChat); Opcode(o3_wipeDownMouseItem); Opcode(o3_dummy); @@ -1220,7 +1233,7 @@ void KyraEngine_MR::setupOpcodeTable() { // 0x40 Opcode(o3_checkInRect); Opcode(o3_updateConversations); - OpcodeUnImpl(); + Opcode(o3_removeItemSlot); Opcode(o3_dummy); // 0x44 Opcode(o3_dummy); @@ -1248,19 +1261,19 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_setMalcolmPos); Opcode(o3_stopMusic); // 0x58 - Opcode(o2_playWanderScoreViaMap); + Opcode(o1_playWanderScoreViaMap); Opcode(o3_playSoundEffect); Opcode(o3_getScore); Opcode(o3_daggerWarning); // 0x5c - Opcode(o3_blockOutRegion); + Opcode(o3_blockOutWalkableRegion); Opcode(o3_dummy); Opcode(o3_showSceneStringsMessage); OpcodeUnImpl(); // 0x60 - Opcode(o2_getRand); + Opcode(o1_getRand); Opcode(o3_dummy); - Opcode(o2_setDeathHandler); + Opcode(o1_setDeathHandler); Opcode(o3_showGoodConscience); // 0x64 Opcode(o3_goodConscienceChat); @@ -1366,7 +1379,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_dummy); // 0x0a Opcode(o2a_setResetFrame); - Opcode(o2_getRand); + Opcode(o1_getRand); Opcode(o3_getMalcolmShapes); Opcode(o3_dummy); @@ -1374,8 +1387,8 @@ void KyraEngine_MR::setupOpcodeTable() { // 0x00 Opcode(o3d_updateAnim); Opcode(o3d_delay); - Opcode(o2_getRand); - Opcode(o2_queryGameFlag); + Opcode(o1_getRand); + Opcode(o1_queryGameFlag); // 0x04 Opcode(o3_dummy); } diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 67e076cbf8..4ad6464424 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -31,7 +31,7 @@ namespace Kyra { -TIMInterpreter::TIMInterpreter(KyraEngine *vm, OSystem *system) : _vm(vm), _system(system), _currentTim(0) { +TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, OSystem *system) : _vm(vm), _system(system), _currentTim(0) { #define COMMAND(x) { &TIMInterpreter::x, #x } #define COMMAND_UNIMPL() { 0, 0 } static CommandEntry commandProcs[] = { @@ -118,7 +118,8 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc for (uint i = 0; i < avtlChunkSize; ++i) tim->avtl[i] = READ_LE_UINT16(tim->avtl + i); - for (int i = 0; i < 10; ++i) + int num = (avtlChunkSize < TIM::kCountFuncs) ? avtlChunkSize : (int)TIM::kCountFuncs; + for (int i = 0; i < num; ++i) tim->func[i].avtl = tim->avtl + tim->avtl[i]; return tim; @@ -128,8 +129,8 @@ void TIMInterpreter::unload(TIM *&tim) const { if (!tim) return; - delete [] tim->text; - delete [] tim->avtl; + delete[] tim->text; + delete[] tim->avtl; delete tim; tim = 0; } @@ -145,7 +146,7 @@ void TIMInterpreter::exec(TIM *tim, bool loop) { } do { - for (_currentFunc = 0; _currentFunc < 10; ++_currentFunc) { + for (_currentFunc = 0; _currentFunc < TIM::kCountFuncs; ++_currentFunc) { TIM::Function &cur = _currentTim->func[_currentFunc]; if (_currentTim->procFunc != -1) @@ -184,6 +185,18 @@ void TIMInterpreter::exec(TIM *tim, bool loop) { } while (loop); } +void TIMInterpreter::refreshTimersAfterPause(uint32 elapsedTime) { + if (!_currentTim) + return; + + for (int i = 0; i < TIM::kCountFuncs; i++) { + if (_currentTim->func[i].lastTime) + _currentTim->func[i].lastTime += elapsedTime; + if (_currentTim->func[i].nextTime) + _currentTim->func[i].nextTime += elapsedTime; + } +} + int TIMInterpreter::execCommand(int cmd, const uint16 *param) { if (cmd < 0 || cmd >= _commandsSize) { warning("Calling unimplemented TIM command %d", cmd); @@ -206,7 +219,7 @@ int TIMInterpreter::cmd_initFunc0(const uint16 *param) { } int TIMInterpreter::cmd_stopCurFunc(const uint16 *param) { - if (_currentFunc < 10) + if (_currentFunc < TIM::kCountFuncs) _currentTim->func[_currentFunc].ip = 0; if (!_currentFunc) _finished = true; @@ -215,7 +228,7 @@ int TIMInterpreter::cmd_stopCurFunc(const uint16 *param) { int TIMInterpreter::cmd_initFunc(const uint16 *param) { uint16 func = *param; - assert(func < 10); + assert(func < TIM::kCountFuncs); if (_currentTim->func[func].avtl) _currentTim->func[func].ip = _currentTim->func[func].avtl; else @@ -225,13 +238,13 @@ int TIMInterpreter::cmd_initFunc(const uint16 *param) { int TIMInterpreter::cmd_stopFunc(const uint16 *param) { uint16 func = *param; - assert(func < 10); + assert(func < TIM::kCountFuncs); _currentTim->func[func].ip = 0; return 1; } int TIMInterpreter::cmd_resetAllRuntimes(const uint16 *param) { - for (int i = 0; i < 10; ++i) { + for (int i = 0; i < TIM::kCountFuncs; ++i) { if (_currentTim->func[i].ip) _currentTim->func[i].nextTime = _system->getMillis(); } @@ -255,7 +268,7 @@ int TIMInterpreter::cmd_execOpcode(const uint16 *param) { int TIMInterpreter::cmd_initFuncNow(const uint16 *param) { uint16 func = *param; - assert(func < 10); + assert(func < TIM::kCountFuncs); _currentTim->func[func].ip = _currentTim->func[func].avtl; _currentTim->func[func].lastTime = _currentTim->func[func].nextTime = _system->getMillis(); return 1; @@ -263,7 +276,7 @@ int TIMInterpreter::cmd_initFuncNow(const uint16 *param) { int TIMInterpreter::cmd_stopFuncNow(const uint16 *param) { uint16 func = *param; - assert(func < 10); + assert(func < TIM::kCountFuncs); _currentTim->func[func].ip = 0; _currentTim->func[func].lastTime = _currentTim->func[func].nextTime = _system->getMillis(); return 1; diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index 2ffbf89d65..cd715ff4ef 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -26,7 +26,7 @@ #ifndef KYRA_SCRIPT_TIM_H #define KYRA_SCRIPT_TIM_H -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "common/array.h" #include "common/func.h" @@ -40,6 +40,10 @@ struct TIM { int16 procFunc; uint16 procParam; + enum { + kCountFuncs = 10 + }; + struct Function { const uint16 *ip; @@ -47,7 +51,7 @@ struct TIM { uint32 nextTime; const uint16 *avtl; - } func[10]; + } func[kCountFuncs]; uint16 *avtl; uint8 *text; @@ -57,7 +61,7 @@ struct TIM { class TIMInterpreter { public: - TIMInterpreter(KyraEngine *vm, OSystem *system); + TIMInterpreter(KyraEngine_v1 *vm, OSystem *system); TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes); void unload(TIM *&tim) const; @@ -69,8 +73,9 @@ public: void stopCurFunc() { if (_currentTim) cmd_stopCurFunc(0); } void play(const char *filename); + void refreshTimersAfterPause(uint32 elapsedTime); private: - KyraEngine *_vm; + KyraEngine_v1 *_vm; OSystem *_system; TIM *_currentTim; diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp index a258482802..f74c7e3560 100644 --- a/engines/kyra/script_v1.cpp +++ b/engines/kyra/script_v1.cpp @@ -23,74 +23,10 @@ * */ - -#include "common/endian.h" -#include "common/system.h" - #include "kyra/kyra_v1.h" -#include "kyra/script.h" #include "kyra/screen.h" -#include "kyra/sprites.h" -#include "kyra/wsamovie.h" -#include "kyra/animator_v1.h" -#include "kyra/text.h" -#include "kyra/timer.h" namespace Kyra { -int KyraEngine_v1::o1_magicInMouseItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - magicInMouseItem(stackPos(0), stackPos(1), -1); - return 0; -} - -int KyraEngine_v1::o1_characterSays(EMCState *script) { - _skipFlag = false; - if (_flags.isTalkie) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_characterSays(%p) (%d, '%s', %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); - characterSays(stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); - } else { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_characterSays(%p) ('%s', %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2)); - const char *string = stackPosString(0); - - if ((_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) && _flags.lang == Common::JA_JPN) { - static const uint8 townsString1[] = { - 0x83, 0x75, 0x83, 0x89, 0x83, 0x93, 0x83, 0x83, 0x93, 0x81, - 0x41, 0x82, 0xDC, 0x82, 0xBD, 0x97, 0x88, 0x82, 0xBD, 0x82, - 0xCC, 0x82, 0xA9, 0x81, 0x48, 0x00, 0x00, 0x00 - }; - static const uint8 townsString2[] = { - 0x83, 0x75, 0x83, 0x89, 0x83, 0x93, 0x83, 0x5C, 0x83, 0x93, - 0x81, 0x41, 0x82, 0xDC, 0x82, 0xBD, 0x97, 0x88, 0x82, 0xBD, - 0x82, 0xCC, 0x82, 0xA9, 0x81, 0x48, 0x00, 0x00 - }; - - if (strncmp((const char *)townsString1, string, sizeof(townsString1)) == 0) - string = (const char *)townsString2; - } - - characterSays(-1, string, stackPos(1), stackPos(2)); - } - - return 0; -} - -int KyraEngine_v1::o1_pauseTicks(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_pauseTicks(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - if (stackPos(1)) { - warning("STUB: special o1_pauseTicks"); - // delete this after correct implementing - delayWithTicks(stackPos(0)); - } else { - delayWithTicks(stackPos(0)); - } - return 0; -} - -int KyraEngine_v1::o1_drawSceneAnimShape(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_drawSceneAnimShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - _screen->drawShape(stackPos(4), _sprites->_sceneShapes[stackPos(0)], stackPos(1), stackPos(2), 0, (stackPos(3) != 0) ? 1 : 0); - return 0; -} int KyraEngine_v1::o1_queryGameFlag(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_queryGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); @@ -107,1408 +43,21 @@ int KyraEngine_v1::o1_resetGameFlag(EMCState *script) { return resetGameFlag(stackPos(0)); } -int KyraEngine_v1::o1_runNPCScript(EMCState *script) { - warning("STUB: o1_runNPCScript"); - return 0; -} - -int KyraEngine_v1::o1_setSpecialExitList(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setSpecialExitList(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); - - for (int i = 0; i < 10; ++i) - _exitList[i] = stackPos(i); - _exitListPtr = _exitList; - - return 0; -} - -int KyraEngine_v1::o1_blockInWalkableRegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _screen->blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); - return 0; -} - -int KyraEngine_v1::o1_blockOutWalkableRegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _screen->blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); - return 0; -} - -int KyraEngine_v1::o1_walkPlayerToPoint(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_walkPlayerToPoint(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - - int normalTimers = stackPos(2); - if (!normalTimers) { - _timer->disable(19); - _timer->disable(14); - _timer->disable(18); - } - - int reinitScript = handleSceneChange(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - - if (!normalTimers) { - _timer->enable(19); - _timer->enable(14); - _timer->enable(18); - } - - if (reinitScript) - _emc->init(script, script->dataPtr); - - if (_sceneChangeState) { - _sceneChangeState = 0; - return 1; - } - return 0; -} - -int KyraEngine_v1::o1_dropItemInScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_dropItemInScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - int item = stackPos(0); - int xpos = stackPos(1); - int ypos = stackPos(2); - - byte freeItem = findFreeItemInScene(_currentCharacter->sceneId); - if (freeItem != 0xFF) { - int sceneId = _currentCharacter->sceneId; - Room *room = &_roomTable[sceneId]; - room->itemsXPos[freeItem] = xpos; - room->itemsYPos[freeItem] = ypos; - room->itemsTable[freeItem] = item; - - _animator->animAddGameItem(freeItem, sceneId); - _animator->updateAllObjectShapes(); - } else { - if (item == 43) - placeItemInGenericMapScene(item, 0); - else - placeItemInGenericMapScene(item, 1); - } - return 0; -} - -int KyraEngine_v1::o1_drawAnimShapeIntoScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_drawAnimShapeIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _screen->hideMouse(); - _animator->restoreAllObjectBackgrounds(); - int shape = stackPos(0); - int xpos = stackPos(1); - int ypos = stackPos(2); - int flags = (stackPos(3) != 0) ? 1 : 0; - _screen->drawShape(2, _sprites->_sceneShapes[shape], xpos, ypos, 0, flags); - _screen->drawShape(0, _sprites->_sceneShapes[shape], xpos, ypos, 0, flags); - _animator->flagAllObjectsForBkgdChange(); - _animator->preserveAnyChangedBackgrounds(); - _animator->flagAllObjectsForRefresh(); - _animator->updateAllObjectShapes(); - _screen->showMouse(); - return 0; -} - -int KyraEngine_v1::o1_createMouseItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_createMouseItem(%p) (%d)", (const void *)script, stackPos(0)); - createMouseItem(stackPos(0)); - return 0; -} - -int KyraEngine_v1::o1_savePageToDisk(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_savePageToDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); - _screen->savePageToDisk(stackPosString(0), stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_sceneAnimOn(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_sceneAnimOn(%p) (%d)", (const void *)script, stackPos(0)); - _sprites->_anims[stackPos(0)].play = true; - return 0; -} - -int KyraEngine_v1::o1_sceneAnimOff(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_sceneAnimOff(%p) (%d)", (const void *)script, stackPos(0)); - _sprites->_anims[stackPos(0)].play = false; - return 0; -} - -int KyraEngine_v1::o1_getElapsedSeconds(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getElapsedSeconds(%p) ()", (const void *)script); - return _system->getMillis() / 1000; -} - -int KyraEngine_v1::o1_mouseIsPointer(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_mouseIsPointer(%p) ()", (const void *)script); - if (_itemInHand == -1) - return 1; - return 0; -} - -int KyraEngine_v1::o1_destroyMouseItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_destroyMouseItem(%p) ()", (const void *)script); - destroyMouseItem(); - return 0; -} - -int KyraEngine_v1::o1_runSceneAnimUntilDone(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_runSceneAnimUntilDone(%p) (%d)", (const void *)script, stackPos(0)); - _screen->hideMouse(); - _animator->restoreAllObjectBackgrounds(); - _sprites->_anims[stackPos(0)].play = true; - _animator->sprites()[stackPos(0)].active = 1; - _animator->flagAllObjectsForBkgdChange(); - _animator->preserveAnyChangedBackgrounds(); - while (_sprites->_anims[stackPos(0)].play) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - delay(10); - } - _animator->restoreAllObjectBackgrounds(); - _screen->showMouse(); - return 0; -} - -int KyraEngine_v1::o1_fadeSpecialPalette(EMCState *script) { - if (_flags.platform == Common::kPlatformAmiga) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - if (_currentCharacter->sceneId != 45) { - if (stackPos(0) == 13) { - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3); - _screen->setScreenPalette(_screen->getPalette(0)); - } - } else { - warning("KyraEngine_v1::o1_fadeSpecialPalette not implemented"); - } - } else { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _screen->fadeSpecialPalette(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - } - return 0; -} - -int KyraEngine_v1::o1_playAdlibSound(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playAdlibSound(%p) (%d)", (const void *)script, stackPos(0)); - snd_playSoundEffect(stackPos(0)); - return 0; -} - -int KyraEngine_v1::o1_playAdlibScore(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playAdlibScore(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - snd_playWanderScoreViaMap(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_phaseInSameScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_phaseInSameScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - transcendScenes(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_setScenePhasingFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setScenePhasingFlag(%p) ()", (const void *)script); - _scenePhasingFlag = 1; - return 1; -} - -int KyraEngine_v1::o1_resetScenePhasingFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_resetScenePhasingFlag(%p) ()", (const void *)script); - _scenePhasingFlag = 0; - return 0; -} - -int KyraEngine_v1::o1_queryScenePhasingFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_queryScenePhasingFlag(%p) ()", (const void *)script); - return _scenePhasingFlag; -} - -int KyraEngine_v1::o1_sceneToDirection(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_sceneToDirection(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert(stackPos(0) < _roomTableSize); - Room *curRoom = &_roomTable[stackPos(0)]; - uint16 returnValue = 0xFFFF; - switch (stackPos(1)) { - case 0: - returnValue = curRoom->northExit; - break; - - case 2: - returnValue = curRoom->eastExit; - break; - - case 4: - returnValue = curRoom->southExit; - break; - - case 6: - returnValue = curRoom->westExit; - break; - - default: - break; - } - if (returnValue == 0xFFFF) - return -1; - return returnValue; -} - -int KyraEngine_v1::o1_setBirthstoneGem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setBirthstoneGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - int index = stackPos(0); - if (index < 4 && index >= 0) { - _birthstoneGemTable[index] = stackPos(1); - return 1; - } - return 0; -} - -int KyraEngine_v1::o1_placeItemInGenericMapScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_placeItemInGenericMapScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - placeItemInGenericMapScene(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_setBrandonStatusBit(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); - _brandonStatusBit |= stackPos(0); - return 0; -} - -int KyraEngine_v1::o1_pauseSeconds(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_pauseSeconds(%p) (%d)", (const void *)script, stackPos(0)); - if (stackPos(0) > 0 && !_skipFlag) - delay(stackPos(0)*1000, true); - _skipFlag = false; - return 0; -} - -int KyraEngine_v1::o1_getCharactersLocation(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getCharactersLocation(%p) (%d)", (const void *)script, stackPos(0)); - return _characterList[stackPos(0)].sceneId; -} - -int KyraEngine_v1::o1_runNPCSubscript(EMCState *script) { - warning("STUB: o1_runNPCSubscript"); - return 0; -} - -int KyraEngine_v1::o1_magicOutMouseItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_magicOutMouseItem(%p) (%d)", (const void *)script, stackPos(0)); - magicOutMouseItem(stackPos(0), -1); - return 0; -} - -int KyraEngine_v1::o1_internalAnimOn(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_internalAnimOn(%p) (%d)", (const void *)script, stackPos(0)); - _animator->sprites()[stackPos(0)].active = 1; - return 0; -} - -int KyraEngine_v1::o1_forceBrandonToNormal(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_forceBrandonToNormal(%p) ()", (const void *)script); - checkAmuletAnimFlags(); - return 0; -} - -int KyraEngine_v1::o1_poisonDeathNow(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_poisonDeathNow(%p) ()", (const void *)script); - seq_poisonDeathNow(1); - return 0; -} - -int KyraEngine_v1::o1_setScaleMode(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setScaleMode(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - int len = stackPos(0); - int setValue1 = stackPos(1); - int start2 = stackPos(2); - int setValue2 = stackPos(3); - for (int i = 0; i < len; ++i) - _scaleTable[i] = setValue1; - int temp = setValue2 - setValue1; - int temp2 = start2 - len; - for (int i = len, offset = 0; i < start2; ++i, ++offset) - _scaleTable[i] = (offset * temp) / temp2 + setValue1; - for (int i = start2; i < 145; ++i) - _scaleTable[i] = setValue2; - _scaleMode = 1; - return _scaleMode; -} - -int KyraEngine_v1::o1_openWSAFile(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_openWSAFile(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3)); - - const char *filename = stackPosString(0); - int wsaIndex = stackPos(1); - - _movieObjects[wsaIndex]->open(filename, (stackPos(3) != 0) ? 1 : 0, 0); - assert(_movieObjects[wsaIndex]->opened()); - - return 0; -} - -int KyraEngine_v1::o1_closeWSAFile(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_closeWSAFile(%p) (%d)", (const void *)script, stackPos(0)); - - int wsaIndex = stackPos(0); - if (_movieObjects[wsaIndex]) - _movieObjects[wsaIndex]->close(); - - return 0; -} - -int KyraEngine_v1::o1_runWSAFromBeginningToEnd(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_runWSAFromBeginningToEnd(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - - _screen->hideMouse(); - - bool running = true; - - int xpos = stackPos(0); - int ypos = stackPos(1); - int waitTime = stackPos(2); - int wsaIndex = stackPos(3); - int worldUpdate = stackPos(4); - int wsaFrame = 0; - - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); - while (running) { - _movieObjects[wsaIndex]->displayFrame(wsaFrame++); - _animator->_updateScreen = true; - if (wsaFrame >= _movieObjects[wsaIndex]->frames()) - running = false; - - uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - while (_system->getMillis() < continueTime) { - if (worldUpdate) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - } else { - _screen->updateScreen(); - } - if (continueTime - _system->getMillis() >= 10) - delay(10); - } - } - - _screen->showMouse(); - - return 0; -} - -int KyraEngine_v1::o1_displayWSAFrame(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_displayWSAFrame(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - int frame = stackPos(0); - int xpos = stackPos(1); - int ypos = stackPos(2); - int waitTime = stackPos(3); - int wsaIndex = stackPos(4); - _screen->hideMouse(); - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); - _movieObjects[wsaIndex]->displayFrame(frame); - _animator->_updateScreen = true; - uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - while (_system->getMillis() < continueTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - if (_skipFlag) - break; - - if (continueTime - _system->getMillis() >= 10) - delay(10); - } - _screen->showMouse(); - return 0; -} - -int KyraEngine_v1::o1_enterNewScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - enterNewScene(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - return 0; -} - -int KyraEngine_v1::o1_setSpecialEnterXAndY(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setSpecialEnterXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _brandonPosX = stackPos(0); - _brandonPosY = stackPos(1); - if (_brandonPosX + 1 == 0 && _brandonPosY + 1 == 0) - _currentCharacter->currentAnimFrame = 88; - return 0; -} - -int KyraEngine_v1::o1_runWSAFrames(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_runWSAFrames(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - int xpos = stackPos(0); - int ypos = stackPos(1); - int delayTime = stackPos(2); - int startFrame = stackPos(3); - int endFrame = stackPos(4); - int wsaIndex = stackPos(5); - _screen->hideMouse(); - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); - for (; startFrame <= endFrame; ++startFrame) { - uint32 nextRun = _system->getMillis() + delayTime * _tickLength; - _movieObjects[wsaIndex]->displayFrame(startFrame); - _animator->_updateScreen = true; - while (_system->getMillis() < nextRun) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - if (nextRun - _system->getMillis() >= 10) - delay(10); - } - } - _screen->showMouse(); - return 0; -} - -int KyraEngine_v1::o1_popBrandonIntoScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_popBrandonIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - int changeScaleMode = stackPos(3); - int xpos = (int16)(stackPos(0) & 0xFFFC); - int ypos = (int16)(stackPos(1) & 0xFFFE); - int facing = stackPos(2); - _currentCharacter->x1 = _currentCharacter->x2 = xpos; - _currentCharacter->y1 = _currentCharacter->y2 = ypos; - _currentCharacter->facing = facing; - _currentCharacter->currentAnimFrame = 7; - int xOffset = _defaultShapeTable[0].xOffset; - int yOffset = _defaultShapeTable[0].yOffset; - int width = _defaultShapeTable[0].w << 3; - int height = _defaultShapeTable[0].h; - Animator_v1::AnimObject *curAnim = _animator->actors(); - - if (changeScaleMode) { - curAnim->x1 = _currentCharacter->x1; - curAnim->y1 = _currentCharacter->y1; - _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1]; - _animator->_brandonScaleX = _animator->_brandonScaleY; - - int animWidth = _animator->fetchAnimWidth(curAnim->sceneAnimPtr, _animator->_brandonScaleX) >> 1; - int animHeight = _animator->fetchAnimHeight(curAnim->sceneAnimPtr, _animator->_brandonScaleY); - - animWidth = (xOffset * animWidth) / width; - animHeight = (yOffset * animHeight) / height; - - curAnim->x2 = curAnim->x1 += animWidth; - curAnim->y2 = curAnim->y1 += animHeight; - } else { - curAnim->x2 = curAnim->x1 = _currentCharacter->x1 + xOffset; - curAnim->y2 = curAnim->y1 = _currentCharacter->y1 + yOffset; - } - - int scaleModeBackup = _scaleMode; - if (changeScaleMode) - _scaleMode = 1; - - _animator->animRefreshNPC(0); - _animator->preserveAllBackgrounds(); - _animator->prepDrawAllObjects(); - _animator->copyChangedObjectsForward(0); - - _scaleMode = scaleModeBackup; - - return 0; -} - -int KyraEngine_v1::o1_restoreAllObjectBackgrounds(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_restoreAllObjectBackgrounds(%p) (%d)", (const void *)script, stackPos(0)); - int disable = stackPos(0); - int activeBackup = 0; - if (disable) { - activeBackup = _animator->actors()->active; - _animator->actors()->active = 0; - } - _animator->restoreAllObjectBackgrounds(); - if (disable) - _animator->actors()->active = activeBackup; - return 0; -} - -int KyraEngine_v1::o1_setCustomPaletteRange(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3); - return 0; -} - -int KyraEngine_v1::o1_loadPageFromDisk(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_loadPageFromDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); - _screen->loadPageFromDisk(stackPosString(0), stackPos(1)); - _animator->_updateScreen = true; - return 0; -} - -int KyraEngine_v1::o1_customPrintTalkString(EMCState *script) { - if (_flags.isTalkie) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_customPrintTalkString(%p) (%d, '%s', %d, %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF); - - if (speechEnabled()) { - snd_voiceWaitForFinish(); - snd_playVoiceFile(stackPos(0)); - } - - _skipFlag = false; - if (textEnabled()) - _text->printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2); - } else { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_customPrintTalkString(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF); - _skipFlag = false; - _text->printTalkTextMessage(stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, 0, 2); - } - _screen->updateScreen(); - return 0; -} - -int KyraEngine_v1::o1_restoreCustomPrintBackground(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_restoreCustomPrintBackground(%p) ()", (const void *)script); - _text->restoreTalkTextMessageBkgd(2, 0); - return 0; +int KyraEngine_v1::o1_getRand(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < stackPos(1)); + return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); } int KyraEngine_v1::o1_hideMouse(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_hideMouse(%p) ()", (const void *)script); - _screen->hideMouse(); + screen()->hideMouse(); return 0; } int KyraEngine_v1::o1_showMouse(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_showMouse(%p) ()", (const void *)script); - _screen->showMouse(); - return 0; -} - -int KyraEngine_v1::o1_getCharacterX(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getCharacterX(%p) (%d)", (const void *)script, stackPos(0)); - return _characterList[stackPos(0)].x1; -} - -int KyraEngine_v1::o1_getCharacterY(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getCharacterY(%p) (%d)", (const void *)script, stackPos(0)); - return _characterList[stackPos(0)].y1; -} - -int KyraEngine_v1::o1_changeCharactersFacing(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_changeCharactersFacing(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - int character = stackPos(0); - int facing = stackPos(1); - int newAnimFrame = stackPos(2); - - _animator->restoreAllObjectBackgrounds(); - if (newAnimFrame != -1) - _characterList[character].currentAnimFrame = newAnimFrame; - _characterList[character].facing = facing; - _animator->animRefreshNPC(character); - _animator->preserveAllBackgrounds(); - _animator->prepDrawAllObjects(); - _animator->copyChangedObjectsForward(0); - - return 0; -} - -int KyraEngine_v1::o1_copyWSARegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_copyWSARegion(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - int xpos = stackPos(0); - int ypos = stackPos(1); - int width = stackPos(2); - int height = stackPos(3); - int srcPage = stackPos(4); - int dstPage = stackPos(5); - _screen->copyRegion(xpos, ypos, xpos, ypos, width, height, srcPage, dstPage); - _animator->_updateScreen = true; - return 0; -} - -int KyraEngine_v1::o1_printText(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_printText(%p) ('%s', %d, %d, 0x%X, 0x%X)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - if (_flags.lang == Common::JA_JPN && stackPos(3) == 7) - _screen->printText(stackPosString(0), stackPos(1), stackPos(2), 0, 0x80); - else - _screen->printText(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - _screen->updateScreen(); - return 0; -} - -int KyraEngine_v1::o1_random(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_random(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert(stackPos(0) < stackPos(1)); - return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); -} - -int KyraEngine_v1::o1_loadSoundFile(EMCState *script) { - warning("STUB: o1_loadSoundFile"); - return 0; -} - -int KyraEngine_v1::o1_displayWSAFrameOnHidPage(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_displayWSAFrameOnHidPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - int frame = stackPos(0); - int xpos = stackPos(1); - int ypos = stackPos(2); - int waitTime = stackPos(3); - int wsaIndex = stackPos(4); - - _screen->hideMouse(); - uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(2); - _movieObjects[wsaIndex]->displayFrame(frame); - _animator->_updateScreen = true; - while (_system->getMillis() < continueTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - if (_skipFlag) - break; - - if (continueTime - _system->getMillis() >= 10) - delay(10); - } - _screen->showMouse(); - - return 0; -} - -int KyraEngine_v1::o1_displayWSASequentialFrames(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6)); - int startFrame = stackPos(0); - int endFrame = stackPos(1); - int xpos = stackPos(2); - int ypos = stackPos(3); - int waitTime = stackPos(4); - int wsaIndex = stackPos(5); - int maxTime = stackPos(6); - if (maxTime - 1 <= 0) - maxTime = 1; - - _movieObjects[wsaIndex]->setX(xpos); - _movieObjects[wsaIndex]->setY(ypos); - _movieObjects[wsaIndex]->setDrawPage(0); - - // Workaround for bug #1498221 "KYRA1: Glitches when meeting Zanthia" - // the original didn't do a forced screen update after displaying a wsa frame - // while we have to do it, which make brandon disappear for a short moment, - // what shouldn't happen. So we're not updating the screen for this special - // case too. - if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) { - _movieObjects[wsaIndex]->displayFrame(18); - delay(waitTime * _tickLength); - return 0; - } - - int curTime = 0; - _screen->hideMouse(); - while (curTime < maxTime) { - if (endFrame >= startFrame) { - int frame = startFrame; - while (endFrame >= frame) { - uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame); - _animator->_updateScreen = true; - while (_system->getMillis() < continueTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - if (_skipFlag) - break; - - if (continueTime - _system->getMillis() >= 10) - delay(10); - } - ++frame; - } - } else { - int frame = startFrame; - while (endFrame <= frame) { - uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame); - _animator->_updateScreen = true; - while (_system->getMillis() < continueTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - if (_skipFlag) - break; - - if (continueTime - _system->getMillis() >= 10) - delay(10); - } - --frame; - } - } - - if (_skipFlag) - break; - else - ++curTime; - } - _screen->showMouse(); - - return 0; -} - -int KyraEngine_v1::o1_drawCharacterStanding(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_drawCharacterStanding(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - int character = stackPos(0); - int animFrame = stackPos(1); - int newFacing = stackPos(2); - int updateShapes = stackPos(3); - _characterList[character].currentAnimFrame = animFrame; - if (newFacing != -1) - _characterList[character].facing = newFacing; - _animator->animRefreshNPC(character); - if (updateShapes) - _animator->updateAllObjectShapes(); - return 0; -} - -int KyraEngine_v1::o1_internalAnimOff(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_internalAnimOff(%p) (%d)", (const void *)script, stackPos(0)); - _animator->sprites()[stackPos(0)].active = 0; - return 0; -} - -int KyraEngine_v1::o1_changeCharactersXAndY(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_changeCharactersXAndY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - Character *ch = &_characterList[stackPos(0)]; - int16 x = stackPos(1); - int16 y = stackPos(2); - if (x != -1 && y != -1) { - x &= 0xFFFC; - y &= 0xFFFE; - } - _animator->restoreAllObjectBackgrounds(); - ch->x1 = ch->x2 = x; - ch->y1 = ch->y2 = y; - _animator->preserveAllBackgrounds(); - return 0; -} - -int KyraEngine_v1::o1_clearSceneAnimatorBeacon(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_clearSceneAnimatorBeacon(%p) ()", (const void *)script); - _sprites->_sceneAnimatorBeaconFlag = 0; - return 0; -} - -int KyraEngine_v1::o1_querySceneAnimatorBeacon(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_querySceneAnimatorBeacon(%p) ()", (const void *)script); - return _sprites->_sceneAnimatorBeaconFlag; -} - -int KyraEngine_v1::o1_refreshSceneAnimator(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_refreshSceneAnimator(%p) ()", (const void *)script); - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - return 0; -} - -int KyraEngine_v1::o1_placeItemInOffScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_placeItemInOffScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - int item = stackPos(0); - int xpos = stackPos(1); - int ypos = stackPos(2); - int sceneId = stackPos(3); - - byte freeItem = findFreeItemInScene(sceneId); - if (freeItem != 0xFF) { - assert(sceneId < _roomTableSize); - Room *room = &_roomTable[sceneId]; - - room->itemsTable[freeItem] = item; - room->itemsXPos[freeItem] = xpos; - room->itemsYPos[freeItem] = ypos; - } - return 0; -} - -int KyraEngine_v1::o1_wipeDownMouseItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_wipeDownMouseItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - _screen->hideMouse(); - wipeDownMouseItem(stackPos(1), stackPos(2)); - destroyMouseItem(); - _screen->showMouse(); - return 0; -} - -int KyraEngine_v1::o1_placeCharacterInOtherScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_placeCharacterInOtherScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - int id = stackPos(0); - int sceneId = stackPos(1); - int xpos = (int16)(stackPos(2) & 0xFFFC); - int ypos = (int16)(stackPos(3) & 0xFFFE); - int facing = stackPos(4); - int animFrame = stackPos(5); - - _characterList[id].sceneId = sceneId; - _characterList[id].x1 = _characterList[id].x2 = xpos; - _characterList[id].y1 = _characterList[id].y2 = ypos; - _characterList[id].facing = facing; - _characterList[id].currentAnimFrame = animFrame; - return 0; -} - -int KyraEngine_v1::o1_getKey(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getKey(%p) ()", (const void *)script); - waitForEvent(); - return 0; -} - -int KyraEngine_v1::o1_specificItemInInventory(EMCState *script) { - warning("STUB: o1_specificItemInInventory"); - return 0; -} - -int KyraEngine_v1::o1_popMobileNPCIntoScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_popMobileNPCIntoScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE)); - int character = stackPos(0); - int sceneId = stackPos(1); - int animFrame = stackPos(2); - int facing = stackPos(3); - int16 xpos = (int16)(stackPos(4) & 0xFFFC); - int8 ypos = (int16)(stackPos(5) & 0xFFFE); - Character *curChar = &_characterList[character]; - - curChar->sceneId = sceneId; - curChar->currentAnimFrame = animFrame; - curChar->facing = facing; - curChar->x1 = curChar->x2 = xpos; - curChar->y1 = curChar->y2 = ypos; - - _animator->animAddNPC(character); - _animator->updateAllObjectShapes(); - return 0; -} - -int KyraEngine_v1::o1_mobileCharacterInScene(EMCState *script) { - warning("STUB: o1_mobileCharacterInScene"); - return 0; -} - -int KyraEngine_v1::o1_hideMobileCharacter(EMCState *script) { - warning("STUB: o1_hideMobileCharacter"); - return 0; -} - -int KyraEngine_v1::o1_unhideMobileCharacter(EMCState *script) { - warning("STUB: o1_unhideMobileCharacter"); - return 0; -} - -int KyraEngine_v1::o1_setCharactersLocation(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setCharactersLocation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - Character *ch = &_characterList[stackPos(0)]; - Animator_v1::AnimObject *animObj = &_animator->actors()[stackPos(0)]; - int newScene = stackPos(1); - if (_currentCharacter->sceneId == ch->sceneId) { - if (_currentCharacter->sceneId != newScene) - animObj->active = 0; - } else if (_currentCharacter->sceneId == newScene) { - if (_currentCharacter->sceneId != ch->sceneId) - animObj->active = 1; - } - - ch->sceneId = stackPos(1); - return 0; -} - -int KyraEngine_v1::o1_walkCharacterToPoint(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_walkCharacterToPoint(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - int character = stackPos(0); - int toX = stackPos(1); - int toY = stackPos(2); - _pathfinderFlag2 = 1; - uint32 nextFrame; - int findWayReturn = findWay(_characterList[character].x1, _characterList[character].y1, toX, toY, _movFacingTable, 150); - _pathfinderFlag2 = 0; - - if (_lastFindWayRet < findWayReturn) - _lastFindWayRet = findWayReturn; - if (findWayReturn == 0x7D00 || findWayReturn == 0) - return 0; - - int *curPos = _movFacingTable; - bool running = true; - while (running) { - bool forceContinue = false; - switch (*curPos) { - case 0: - _characterList[character].facing = 2; - break; - - case 1: - _characterList[character].facing = 1; - break; - - case 2: - _characterList[character].facing = 0; - break; - - case 3: - _characterList[character].facing = 7; - break; - - case 4: - _characterList[character].facing = 6; - break; - - case 5: - _characterList[character].facing = 5; - break; - - case 6: - _characterList[character].facing = 4; - break; - - case 7: - _characterList[character].facing = 3; - break; - - case 8: - running = 0; - break; - - default: - ++curPos; - forceContinue = true; - break; - } - - if (forceContinue || !running) - continue; - - setCharacterPosition(character, 0); - ++curPos; - - nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); - while (_system->getMillis() < nextFrame) { - _sprites->updateSceneAnims(); - updateMousePointer(); - _timer->update(); - _animator->updateAllObjectShapes(); - updateTextFade(); - if ((nextFrame - _system->getMillis()) >= 10) - delay(10); - } - } - return 0; -} - -int KyraEngine_v1::o1_specialEventDisplayBrynnsNote(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_specialEventDisplayBrynnsNote(%p) ()", (const void *)script); - _screen->hideMouse(); - _screen->savePageToDisk("HIDPAGE.TMP", 2); - _screen->savePageToDisk("SEENPAGE.TMP", 0); - if (_flags.isTalkie) { - if (_flags.lang == Common::EN_ANY || _flags.lang == Common::IT_ITA) - _screen->loadBitmap("NOTEENG.CPS", 3, 3, 0); - else if (_flags.lang == Common::FR_FRA) - _screen->loadBitmap("NOTEFRE.CPS", 3, 3, 0); - else if (_flags.lang == Common::DE_DEU) - _screen->loadBitmap("NOTEGER.CPS", 3, 3, 0); - } else { - _screen->loadBitmap("NOTE.CPS", 3, 3, 0); - } - _screen->copyRegion(63, 8, 63, 8, 194, 128, 2, 0); - _screen->updateScreen(); - _screen->showMouse(); - _screen->setFont(Screen::FID_6_FNT); - return 0; -} - -int KyraEngine_v1::o1_specialEventRemoveBrynnsNote(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_specialEventRemoveBrynnsNote(%p) ()", (const void *)script); - _screen->hideMouse(); - _screen->loadPageFromDisk("SEENPAGE.TMP", 0); - _screen->loadPageFromDisk("HIDPAGE.TMP", 2); - _screen->updateScreen(); - _screen->showMouse(); - _screen->setFont(Screen::FID_8_FNT); - return 0; -} - -int KyraEngine_v1::o1_setLogicPage(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setLogicPage(%p) (%d)", (const void *)script, stackPos(0)); - _screen->_curPage = stackPos(0); - return stackPos(0); -} - -int KyraEngine_v1::o1_fatPrint(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fatPrint(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - - // Workaround for bug #1582672 ("KYRA1: Text crippled and drawn wrong") - // I'm not sure how the original handles this, since it seems to call - // printText also, maybe it fails somewhere inside... - // TODO: fix the reason for this workaround - if (_currentRoom == 117) - return 0; - _text->printText(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - return 0; -} - -int KyraEngine_v1::o1_preserveAllObjectBackgrounds(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_preserveAllObjectBackgrounds(%p) ()", (const void *)script); - _animator->preserveAllBackgrounds(); - return 0; -} - -int KyraEngine_v1::o1_updateSceneAnimations(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_updateSceneAnimations(%p) (%d)", (const void *)script, stackPos(0)); - int times = stackPos(0); - while (times--) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - } - return 0; -} - -int KyraEngine_v1::o1_sceneAnimationActive(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_sceneAnimationActive(%p) (%d)", (const void *)script, stackPos(0)); - return _sprites->_anims[stackPos(0)].play; -} - -int KyraEngine_v1::o1_setCharactersMovementDelay(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setCharactersMovementDelay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _timer->setDelay(stackPos(0)+5, stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_getCharactersFacing(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getCharactersFacing(%p) (%d)", (const void *)script, stackPos(0)); - return _characterList[stackPos(0)].facing; -} - -int KyraEngine_v1::o1_bkgdScrollSceneAndMasksRight(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_bkgdScrollSceneAndMasksRight(%p) (%d)", (const void *)script, stackPos(0)); - _screen->copyBackgroundBlock(stackPos(0), 2, 0); - _screen->copyBackgroundBlock2(stackPos(0)); - // update the whole screen - _screen->copyRegion(7, 7, 7, 7, 305, 129, 3, 0); - // Don't do a screen update here, see bug #1910180 "KYRA1: Screen 'flash'" - // it would cause to draw the screen with a wrong palette and thus look - // strange for the user. Since this opcode should be just called on scene - // initialization anyway, there should be no problem with not updating the - // screen right now. - return 0; -} - -int KyraEngine_v1::o1_dispelMagicAnimation(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_dispelMagicAnimation(%p) ()", (const void *)script); - seq_dispelMagicAnimation(); - return 0; -} - -int KyraEngine_v1::o1_findBrightestFireberry(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_findBrightestFireberry(%p) ()", (const void *)script); - if (_currentCharacter->sceneId >= 187 && _currentCharacter->sceneId <= 198) - return 29; - - if (_currentCharacter->sceneId == 133 || _currentCharacter->sceneId == 137 || - _currentCharacter->sceneId == 165 || _currentCharacter->sceneId == 173) - return 29; - - if (_itemInHand == 28) - return 28; - - int brightestFireberry = 107; - if (_itemInHand >= 29 && _itemInHand <= 33) - brightestFireberry = _itemInHand; - for (int i = 0; i < 10; ++i) { - uint8 item = _currentCharacter->inventoryItems[i]; - if (item == 0xFF) - continue; - if (item == 28) - return 28; - if (item >= 29 && item <= 33) { - if (item < brightestFireberry) - brightestFireberry = item; - } - } - assert(_currentCharacter->sceneId < _roomTableSize); - Room *curRoom = &_roomTable[_currentCharacter->sceneId]; - for (int i = 0; i < 12; ++i) { - uint8 item = curRoom->itemsTable[i]; - if (item == 0xFF) - continue; - if (item == 28) - return 28; - if (item >= 29 && item <= 33) { - if (item < brightestFireberry) - brightestFireberry = item; - } - } - if (brightestFireberry == 107) - return -1; - return brightestFireberry; -} - -int KyraEngine_v1::o1_setFireberryGlowPalette(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0)); - int palIndex = 0; - switch (stackPos(0)) { - case 0x1E: - palIndex = 9; - break; - - case 0x1F: - palIndex = 10; - break; - - case 0x20: - palIndex = 11; - break; - - case 0x21: - case -1: - palIndex = 12; - break; - - default: - palIndex = 8; - break; - } - if (_brandonStatusBit & 2) { - if (_currentCharacter->sceneId != 133 && _currentCharacter->sceneId != 137 && - _currentCharacter->sceneId != 165 && _currentCharacter->sceneId != 173 && - (_currentCharacter->sceneId < 187 || _currentCharacter->sceneId > 198)) { - palIndex = 14; - } - } - const uint8 *palette = _specialPalettes[palIndex]; - memcpy(_screen->getPalette(1) + 684, palette, 44); - return 0; -} - -int KyraEngine_v1::o1_setDeathHandlerFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0)); - _deathHandler = stackPos(0); - return 0; -} - -int KyraEngine_v1::o1_drinkPotionAnimation(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_drinkPotionAnimation(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - seq_playDrinkPotionAnim(stackPos(0), stackPos(1), stackPos(2)); - return 0; -} - -int KyraEngine_v1::o1_makeAmuletAppear(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_makeAmuletAppear(%p) ()", (const void *)script); - WSAMovieV1 amulet(this); - amulet.open("AMULET.WSA", 1, 0); - amulet.setX(224); - amulet.setY(152); - amulet.setDrawPage(0); - if (amulet.opened()) { - assert(_amuleteAnim); - _screen->hideMouse(); - snd_playSoundEffect(0x70); - uint32 nextTime = 0; - for (int i = 0; _amuleteAnim[i] != 0xFF; ++i) { - nextTime = _system->getMillis() + 5 * _tickLength; - - uint8 code = _amuleteAnim[i]; - if (code == 3 || code == 7) - snd_playSoundEffect(0x71); - - if (code == 5) - snd_playSoundEffect(0x72); - - if (code == 14) - snd_playSoundEffect(0x73); - - amulet.displayFrame(code); - _animator->_updateScreen = true; - - while (_system->getMillis() < nextTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - if (nextTime - _system->getMillis() >= 10) - delay(10); - } - } - _screen->showMouse(); - } - setGameFlag(0x2D); - return 0; -} - -int KyraEngine_v1::o1_drawItemShapeIntoScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_drawItemShapeIntoScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - int item = stackPos(0); - int x = stackPos(1); - int y = stackPos(2); - int flags = stackPos(3); - int onlyHidPage = stackPos(4); - - if (flags) - flags = 1; - - if (onlyHidPage) { - _screen->drawShape(2, _shapes[216+item], x, y, 0, flags); - } else { - _screen->hideMouse(); - _animator->restoreAllObjectBackgrounds(); - _screen->drawShape(2, _shapes[216+item], x, y, 0, flags); - _screen->drawShape(0, _shapes[216+item], x, y, 0, flags); - _animator->flagAllObjectsForBkgdChange(); - _animator->preserveAnyChangedBackgrounds(); - _animator->flagAllObjectsForRefresh(); - _animator->updateAllObjectShapes(); - _screen->showMouse(); - } - return 0; -} - -int KyraEngine_v1::o1_setCharactersCurrentFrame(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setCharactersCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _characterList[stackPos(0)].currentAnimFrame = stackPos(1); - return 0; -} - -int KyraEngine_v1::o1_waitForConfirmationMouseClick(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_waitForConfirmationMouseClick(%p) ()", (const void *)script); - // if (mouseEnabled) { - while (!_mousePressFlag) { - updateMousePointer(); - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - delay(10); - } - - while (_mousePressFlag) { - updateMousePointer(); - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - delay(10); - } - // } - _gui->processButtonList(_buttonList, 0); - _skipFlag = false; - Common::Point mouse = getMousePos(); - script->regs[1] = mouse.x; - script->regs[2] = mouse.y; - return 0; -} - -int KyraEngine_v1::o1_pageFlip(EMCState *script) { - warning("STUB: o1_pageFlip"); - return 0; -} - -int KyraEngine_v1::o1_setSceneFile(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setSceneFile(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - setSceneFile(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_getItemInMarbleVase(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getItemInMarbleVase(%p) ()", (const void *)script); - return _marbleVaseItem; -} - -int KyraEngine_v1::o1_setItemInMarbleVase(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setItemInMarbleVase(%p) (%d)", (const void *)script, stackPos(0)); - _marbleVaseItem = stackPos(0); - return 0; -} - -int KyraEngine_v1::o1_addItemToInventory(EMCState *script) { - warning("STUB: o1_addItemToInventory"); - return 0; -} - -int KyraEngine_v1::o1_intPrint(EMCState *script) { - warning("STUB: o1_intPrint"); - return 0; -} - -int KyraEngine_v1::o1_shakeScreen(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_shakeScreen(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - int waitTicks = stackPos(1); - int times = stackPos(0); - - for (int i = 0; i < times; ++i) { - _screen->shakeScreen(1); - delay(waitTicks * _tickLength); - } - - return 0; -} - -int KyraEngine_v1::o1_createAmuletJewel(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_createAmuletJewel(%p) (%d)", (const void *)script, stackPos(0)); - seq_createAmuletJewel(stackPos(0), 0, 0, 0); - return 0; -} - -int KyraEngine_v1::o1_setSceneAnimCurrXY(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setSceneAnimCurrXY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - _sprites->_anims[stackPos(0)].x = stackPos(1); - _sprites->_anims[stackPos(0)].y = stackPos(2); - return 0; -} - -int KyraEngine_v1::o1_poisonBrandonAndRemaps(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_poisonBrandonAndRemaps(%p) ()", (const void *)script); - setBrandonPoisonFlags(1); - return 0; -} - -int KyraEngine_v1::o1_fillFlaskWithWater(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fillFlaskWithWater(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - seq_fillFlaskWithWater(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_getCharactersMovementDelay(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getCharactersMovementDelay(%p) (%d)", (const void *)script, stackPos(0)); - return _timer->getDelay(stackPos(0)+5); -} - -int KyraEngine_v1::o1_getBirthstoneGem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getBirthstoneGem(%p) (%d)", (const void *)script, stackPos(0)); - if (stackPos(0) < 4) - return _birthstoneGemTable[stackPos(0)]; - return 0; -} - -int KyraEngine_v1::o1_queryBrandonStatusBit(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_queryBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); - if (_brandonStatusBit & stackPos(0)) - return 1; - return 0; -} - -int KyraEngine_v1::o1_playFluteAnimation(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playFluteAnimation(%p) ()", (const void *)script); - seq_playFluteAnimation(); - return 0; -} - -int KyraEngine_v1::o1_playWinterScrollSequence(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playWinterScrollSequence(%p) (%d)", (const void *)script, stackPos(0)); - if (!stackPos(0)) - seq_winterScroll2(); - else - seq_winterScroll1(); - return 0; -} - -int KyraEngine_v1::o1_getIdolGem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getIdolGem(%p) (%d)", (const void *)script, stackPos(0)); - return _idolGemsTable[stackPos(0)]; -} - -int KyraEngine_v1::o1_setIdolGem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setIdolGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _idolGemsTable[stackPos(0)] = stackPos(1); - return 0; -} - -int KyraEngine_v1::o1_totalItemsInScene(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_totalItemsInScene(%p) (%d)", (const void *)script, stackPos(0)); - return countItemsInScene(stackPos(0)); -} - -int KyraEngine_v1::o1_restoreBrandonsMovementDelay(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_restoreBrandonsMovementDelay(%p) ()", (const void *)script); - setWalkspeed(_configWalkspeed); + screen()->showMouse(); return 0; } @@ -1518,514 +67,58 @@ int KyraEngine_v1::o1_setMousePos(EMCState *script) { return 0; } -int KyraEngine_v1::o1_getMouseState(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getMouseState(%p) ()", (const void *)script); - return _mouseState; -} - -int KyraEngine_v1::o1_setEntranceMouseCursorTrack(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setEntranceMouseCursorTrack(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); - _entranceMouseCursorTracks[0] = stackPos(0); - _entranceMouseCursorTracks[1] = stackPos(1); - _entranceMouseCursorTracks[2] = stackPos(0) + stackPos(2) - 1; - _entranceMouseCursorTracks[3] = stackPos(1) + stackPos(3) - 1; - _entranceMouseCursorTracks[4] = stackPos(4); - return 0; -} - -int KyraEngine_v1::o1_itemAppearsOnGround(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_itemAppearsOnGround(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - processItemDrop(_currentCharacter->sceneId, stackPos(0), stackPos(1), stackPos(2), 2, 0); - return 0; -} - -int KyraEngine_v1::o1_setNoDrawShapesFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setNoDrawShapesFlag(%p) (%d)", (const void *)script, stackPos(0)); - _animator->_noDrawShapesFlag = stackPos(0); - return 0; -} - -int KyraEngine_v1::o1_fadeEntirePalette(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - int cmd = stackPos(0); - uint8 *fadePal = 0; - - if (_flags.platform == Common::kPlatformAmiga) { - if (cmd == 0) { - fadePal = _screen->getPalette(2); - memset(fadePal, 0, 32*3); - memcpy(_screen->getPalette(4), _screen->getPalette(0), 32*3); - } else if (cmd == 1) { - fadePal = _screen->getPalette(0); - memcpy(_screen->getPalette(0), _screen->getPalette(4), 32*3); - } else if (cmd == 2) { - fadePal = _screen->getPalette(0); - memset(_screen->getPalette(2), 0, 32*3); - } - } else { - if (cmd == 0) { - fadePal = _screen->getPalette(2); - uint8 *screenPal = _screen->getPalette(0); - uint8 *backUpPal = _screen->getPalette(3); - - memcpy(backUpPal, screenPal, sizeof(uint8)*768); - memset(fadePal, 0, sizeof(uint8)*768); - } else if (cmd == 1) { - //fadePal = _screen->getPalette(3); - warning("unimplemented o1_fadeEntirePalette function"); - return 0; - } else if (cmd == 2) { - memset(_screen->getPalette(2), 0, 768); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); - fadePal = _screen->getPalette(0); - } - } - - _screen->fadePalette(fadePal, stackPos(1)); - return 0; -} - -int KyraEngine_v1::o1_itemOnGroundHere(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_itemOnGroundHere(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert(stackPos(0) < _roomTableSize); - Room *curRoom = &_roomTable[stackPos(0)]; - for (int i = 0; i < 12; ++i) { - if (curRoom->itemsTable[i] == stackPos(1)) - return 1; - } - return 0; -} - -int KyraEngine_v1::o1_queryCauldronState(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_queryCauldronState(%p) ()", (const void *)script); - return _cauldronState; -} - -int KyraEngine_v1::o1_setCauldronState(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setCauldronState(%p) (%d)", (const void *)script, stackPos(0)); - _cauldronState = stackPos(0); - return _cauldronState; -} - -int KyraEngine_v1::o1_queryCrystalState(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_queryCrystalState(%p) (%d)", (const void *)script, stackPos(0)); - if (!stackPos(0)) - return _crystalState[0]; - else if (stackPos(0) == 1) - return _crystalState[1]; - return -1; -} - -int KyraEngine_v1::o1_setCrystalState(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setCrystalState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - if (!stackPos(0)) - _crystalState[0] = stackPos(1); - else if (stackPos(0) == 1) - _crystalState[1] = stackPos(1); - return stackPos(1); -} - -int KyraEngine_v1::o1_setPaletteRange(EMCState *script) { - warning("STUB: o1_setPaletteRange"); - return 0; -} - -int KyraEngine_v1::o1_shrinkBrandonDown(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_shrinkBrandonDown(%p) (%d)", (const void *)script, stackPos(0)); - int delayTime = stackPos(0); - checkAmuletAnimFlags(); - int scaleValue = _scaleTable[_currentCharacter->y1]; - int scale = 0; - - if (_scaleMode) - scale = scaleValue; - else - scale = 256; - - int scaleModeBackUp = _scaleMode; - _scaleMode = 1; - int scaleEnd = scale >> 1; - for (; scaleEnd <= scale; --scale) { - _scaleTable[_currentCharacter->y1] = scale; - _animator->animRefreshNPC(0); - delayWithTicks(1); - } - delayWithTicks(delayTime); // XXX - _scaleTable[_currentCharacter->y1] = scaleValue; - _scaleMode = scaleModeBackUp; - return 0; -} - -int KyraEngine_v1::o1_growBrandonUp(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_growBrandonUp(%p) ()", (const void *)script); - int scaleValue = _scaleTable[_currentCharacter->y1]; - int scale = 0; - if (_scaleMode) - scale = scaleValue; - else - scale = 256; - - int scaleModeBackUp = _scaleMode; - _scaleMode = 1; - for (int curScale = scale >> 1; curScale <= scale; ++curScale) { - _scaleTable[_currentCharacter->y1] = curScale; - _animator->animRefreshNPC(0); - delayWithTicks(1); - } - _scaleTable[_currentCharacter->y1] = scaleValue; - _scaleMode = scaleModeBackUp; +int KyraEngine_v1::o1_setHandItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setHandItem(%p) (%d)", (const void *)script, stackPos(0)); + setHandItem(stackPos(0)); return 0; } -int KyraEngine_v1::o1_setBrandonScaleXAndY(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setBrandonScaleXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _animator->_brandonScaleX = stackPos(0); - _animator->_brandonScaleY = stackPos(1); +int KyraEngine_v1::o1_removeHandItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_removeHandItem(%p) ()", (const void *)script); + removeHandItem(); return 0; } -int KyraEngine_v1::o1_resetScaleMode(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_resetScaleMode(%p) ()", (const void *)script); - _scaleMode = 0; - return 0; -} - -int KyraEngine_v1::o1_getScaleDepthTableValue(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getScaleDepthTableValue(%p) (%d)", (const void *)script, stackPos(0)); - assert(stackPos(0) < ARRAYSIZE(_scaleTable)); - return _scaleTable[stackPos(0)]; -} - -int KyraEngine_v1::o1_setScaleDepthTableValue(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setScaleDepthTableValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert(stackPos(0) < ARRAYSIZE(_scaleTable)); - _scaleTable[stackPos(0)] = stackPos(1); - return stackPos(1); -} - -int KyraEngine_v1::o1_message(EMCState *script) { - if (_flags.isTalkie) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_message(%p) (%d, '%s', %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2)); - drawSentenceCommand(stackPosString(1), stackPos(2)); - } else { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_message(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); - drawSentenceCommand(stackPosString(0), stackPos(1)); - } - - return 0; -} - -int KyraEngine_v1::o1_checkClickOnNPC(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_checkClickOnNPC(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - return checkForNPCScriptRun(stackPos(0), stackPos(1)); -} - -int KyraEngine_v1::o1_getFoyerItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getFoyerItem(%p) (%d)", (const void *)script, stackPos(0)); - assert(stackPos(0) < ARRAYSIZE(_foyerItemTable)); - return _foyerItemTable[stackPos(0)]; -} - -int KyraEngine_v1::o1_setFoyerItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setFoyerItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert(stackPos(0) < ARRAYSIZE(_foyerItemTable)); - _foyerItemTable[stackPos(0)] = stackPos(1); - return stackPos(1); -} - -int KyraEngine_v1::o1_setNoItemDropRegion(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setNoItemDropRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - addToNoDropRects(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - return 0; -} - -int KyraEngine_v1::o1_walkMalcolmOn(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_walkMalcolmOn(%p) ()", (const void *)script); - if (!_malcolmFlag) - _malcolmFlag = 1; - return 0; -} - -int KyraEngine_v1::o1_passiveProtection(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_passiveProtection(%p) ()", (const void *)script); - return 1; -} - -int KyraEngine_v1::o1_setPlayingLoop(EMCState *script) { - warning("STUB: o1_setPlayingLoop"); - return 0; -} - -int KyraEngine_v1::o1_brandonToStoneSequence(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_brandonToStoneSequence(%p) ()", (const void *)script); - seq_brandonToStone(); - return 0; -} - -int KyraEngine_v1::o1_brandonHealingSequence(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_brandonHealingSequence(%p) ()", (const void *)script); - seq_brandonHealing(); - return 0; -} - -int KyraEngine_v1::o1_protectCommandLine(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_protectCommandLine(%p) (%d)", (const void *)script, stackPos(0)); - return stackPos(0); +int KyraEngine_v1::o1_getMouseState(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getMouseState(%p) ()", (const void *)script); + return _mouseState; } -int KyraEngine_v1::o1_pauseMusicSeconds(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_pauseMusicSeconds(%p) ()", (const void *)script); - // if music disabled - // return - o1_pauseSeconds(script); +int KyraEngine_v1::o1_setDeathHandler(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setDeathHandler(%p) (%d)", (const void *)script, stackPos(0)); + _deathHandler = stackPos(0); return 0; } -int KyraEngine_v1::o1_resetMaskRegion(EMCState *script) { - warning("STUB: o1_resetMaskRegion"); +int KyraEngine_v1::o1_playWanderScoreViaMap(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playWanderScoreViaMap(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + snd_playWanderScoreViaMap(stackPos(0), stackPos(1)); return 0; } -int KyraEngine_v1::o1_setPaletteChangeFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setPaletteChangeFlag(%p) (%d)", (const void *)script, stackPos(0)); - _paletteChanged = stackPos(0); - return _paletteChanged; -} - int KyraEngine_v1::o1_fillRect(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fillRect(%p) (%d, %d, %d, %d, %d, 0x%X)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - int videoPageBackup = _screen->_curPage; - _screen->_curPage = stackPos(0); - _screen->fillRect(stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - _screen->_curPage = videoPageBackup; + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fillRect(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + screen()->fillRect(stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(0)); return 0; } -int KyraEngine_v1::o1_vocUnload(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_vocUnload(%p) ()", (const void *)script); - // this should unload all voc files (not needed) +int KyraEngine_v1::o1_blockInWalkableRegion(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + screen()->blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); return 0; } -int KyraEngine_v1::o1_vocLoad(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_vocLoad(%p) (%d)", (const void *)script, stackPos(0)); - // this should load the specified voc file (not needed) +int KyraEngine_v1::o1_blockOutWalkableRegion(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + screen()->blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); return 0; } -int KyraEngine_v1::o1_dummy(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_dummy(%p) ()", (const void *)script); +int KyraEngine_v1::o1_playSoundEffect(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playSoundEffect(%p) (%d)", (const void *)script, stackPos(0)); + snd_playSoundEffect(stackPos(0)); return 0; } -#pragma mark - - -typedef Common::Functor1Mem<EMCState*, int, KyraEngine_v1> OpcodeV1; -#define SetOpcodeTable(x) table = &x; -#define Opcode(x) table->push_back(new OpcodeV1(this, &KyraEngine_v1::x)) -void KyraEngine_v1::setupOpcodeTable() { - Common::Array<const Opcode *> *table = 0; - - SetOpcodeTable(_opcodes); - // 0x00 - Opcode(o1_magicInMouseItem); - Opcode(o1_characterSays); - Opcode(o1_pauseTicks); - Opcode(o1_drawSceneAnimShape); - // 0x04 - Opcode(o1_queryGameFlag); - Opcode(o1_setGameFlag); - Opcode(o1_resetGameFlag); - Opcode(o1_runNPCScript); - // 0x08 - Opcode(o1_setSpecialExitList); - Opcode(o1_blockInWalkableRegion); - Opcode(o1_blockOutWalkableRegion); - Opcode(o1_walkPlayerToPoint); - // 0x0c - Opcode(o1_dropItemInScene); - Opcode(o1_drawAnimShapeIntoScene); - Opcode(o1_createMouseItem); - Opcode(o1_savePageToDisk); - // 0x10 - Opcode(o1_sceneAnimOn); - Opcode(o1_sceneAnimOff); - Opcode(o1_getElapsedSeconds); - Opcode(o1_mouseIsPointer); - // 0x14 - Opcode(o1_destroyMouseItem); - Opcode(o1_runSceneAnimUntilDone); - Opcode(o1_fadeSpecialPalette); - Opcode(o1_playAdlibSound); - // 0x18 - Opcode(o1_playAdlibScore); - Opcode(o1_phaseInSameScene); - Opcode(o1_setScenePhasingFlag); - Opcode(o1_resetScenePhasingFlag); - // 0x1c - Opcode(o1_queryScenePhasingFlag); - Opcode(o1_sceneToDirection); - Opcode(o1_setBirthstoneGem); - Opcode(o1_placeItemInGenericMapScene); - // 0x20 - Opcode(o1_setBrandonStatusBit); - Opcode(o1_pauseSeconds); - Opcode(o1_getCharactersLocation); - Opcode(o1_runNPCSubscript); - // 0x24 - Opcode(o1_magicOutMouseItem); - Opcode(o1_internalAnimOn); - Opcode(o1_forceBrandonToNormal); - Opcode(o1_poisonDeathNow); - // 0x28 - Opcode(o1_setScaleMode); - Opcode(o1_openWSAFile); - Opcode(o1_closeWSAFile); - Opcode(o1_runWSAFromBeginningToEnd); - // 0x2c - Opcode(o1_displayWSAFrame); - Opcode(o1_enterNewScene); - Opcode(o1_setSpecialEnterXAndY); - Opcode(o1_runWSAFrames); - // 0x30 - Opcode(o1_popBrandonIntoScene); - Opcode(o1_restoreAllObjectBackgrounds); - Opcode(o1_setCustomPaletteRange); - Opcode(o1_loadPageFromDisk); - // 0x34 - Opcode(o1_customPrintTalkString); - Opcode(o1_restoreCustomPrintBackground); - Opcode(o1_hideMouse); - Opcode(o1_showMouse); - // 0x38 - Opcode(o1_getCharacterX); - Opcode(o1_getCharacterY); - Opcode(o1_changeCharactersFacing); - Opcode(o1_copyWSARegion); - // 0x3c - Opcode(o1_printText); - Opcode(o1_random); - Opcode(o1_loadSoundFile); - Opcode(o1_displayWSAFrameOnHidPage); - // 0x40 - Opcode(o1_displayWSASequentialFrames); - Opcode(o1_drawCharacterStanding); - Opcode(o1_internalAnimOff); - Opcode(o1_changeCharactersXAndY); - // 0x44 - Opcode(o1_clearSceneAnimatorBeacon); - Opcode(o1_querySceneAnimatorBeacon); - Opcode(o1_refreshSceneAnimator); - Opcode(o1_placeItemInOffScene); - // 0x48 - Opcode(o1_wipeDownMouseItem); - Opcode(o1_placeCharacterInOtherScene); - Opcode(o1_getKey); - Opcode(o1_specificItemInInventory); - // 0x4c - Opcode(o1_popMobileNPCIntoScene); - Opcode(o1_mobileCharacterInScene); - Opcode(o1_hideMobileCharacter); - Opcode(o1_unhideMobileCharacter); - // 0x50 - Opcode(o1_setCharactersLocation); - Opcode(o1_walkCharacterToPoint); - Opcode(o1_specialEventDisplayBrynnsNote); - Opcode(o1_specialEventRemoveBrynnsNote); - // 0x54 - Opcode(o1_setLogicPage); - Opcode(o1_fatPrint); - Opcode(o1_preserveAllObjectBackgrounds); - Opcode(o1_updateSceneAnimations); - // 0x58 - Opcode(o1_sceneAnimationActive); - Opcode(o1_setCharactersMovementDelay); - Opcode(o1_getCharactersFacing); - Opcode(o1_bkgdScrollSceneAndMasksRight); - // 0x5c - Opcode(o1_dispelMagicAnimation); - Opcode(o1_findBrightestFireberry); - Opcode(o1_setFireberryGlowPalette); - Opcode(o1_setDeathHandlerFlag); - // 0x60 - Opcode(o1_drinkPotionAnimation); - Opcode(o1_makeAmuletAppear); - Opcode(o1_drawItemShapeIntoScene); - Opcode(o1_setCharactersCurrentFrame); - // 0x64 - Opcode(o1_waitForConfirmationMouseClick); - Opcode(o1_pageFlip); - Opcode(o1_setSceneFile); - Opcode(o1_getItemInMarbleVase); - // 0x68 - Opcode(o1_setItemInMarbleVase); - Opcode(o1_addItemToInventory); - Opcode(o1_intPrint); - Opcode(o1_shakeScreen); - // 0x6c - Opcode(o1_createAmuletJewel); - Opcode(o1_setSceneAnimCurrXY); - Opcode(o1_poisonBrandonAndRemaps); - Opcode(o1_fillFlaskWithWater); - // 0x70 - Opcode(o1_getCharactersMovementDelay); - Opcode(o1_getBirthstoneGem); - Opcode(o1_queryBrandonStatusBit); - Opcode(o1_playFluteAnimation); - // 0x74 - Opcode(o1_playWinterScrollSequence); - Opcode(o1_getIdolGem); - Opcode(o1_setIdolGem); - Opcode(o1_totalItemsInScene); - // 0x78 - Opcode(o1_restoreBrandonsMovementDelay); - Opcode(o1_setMousePos); - Opcode(o1_getMouseState); - Opcode(o1_setEntranceMouseCursorTrack); - // 0x7c - Opcode(o1_itemAppearsOnGround); - Opcode(o1_setNoDrawShapesFlag); - Opcode(o1_fadeEntirePalette); - Opcode(o1_itemOnGroundHere); - // 0x80 - Opcode(o1_queryCauldronState); - Opcode(o1_setCauldronState); - Opcode(o1_queryCrystalState); - Opcode(o1_setCrystalState); - // 0x84 - Opcode(o1_setPaletteRange); - Opcode(o1_shrinkBrandonDown); - Opcode(o1_growBrandonUp); - Opcode(o1_setBrandonScaleXAndY); - // 0x88 - Opcode(o1_resetScaleMode); - Opcode(o1_getScaleDepthTableValue); - Opcode(o1_setScaleDepthTableValue); - Opcode(o1_message); - // 0x8c - Opcode(o1_checkClickOnNPC); - Opcode(o1_getFoyerItem); - Opcode(o1_setFoyerItem); - Opcode(o1_setNoItemDropRegion); - // 0x90 - Opcode(o1_walkMalcolmOn); - Opcode(o1_passiveProtection); - Opcode(o1_setPlayingLoop); - Opcode(o1_brandonToStoneSequence); - // 0x94 - Opcode(o1_brandonHealingSequence); - Opcode(o1_protectCommandLine); - Opcode(o1_pauseMusicSeconds); - Opcode(o1_resetMaskRegion); - // 0x98 - Opcode(o1_setPaletteChangeFlag); - Opcode(o1_fillRect); - Opcode(o1_vocUnload); - Opcode(o1_vocLoad); - // 0x9c - Opcode(o1_dummy); -} -#undef Opcode - } // end of namespace Kyra diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp index fcfb34561f..2af4fda727 100644 --- a/engines/kyra/script_v2.cpp +++ b/engines/kyra/script_v2.cpp @@ -103,44 +103,6 @@ int KyraEngine_v2::o2_defineItem(EMCState *script) { return freeItem; } -int KyraEngine_v2::o2_queryGameFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_queryGameFlag(%p) (%d)", (const void *)script, stackPos(0)); - return queryGameFlag(stackPos(0)); -} - -int KyraEngine_v2::o2_resetGameFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_resetGameFlag(%p) (%d)", (const void *)script, stackPos(0)); - return resetGameFlag(stackPos(0)); -} - -int KyraEngine_v2::o2_setGameFlag(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setGameFlag(%p) (%d)", (const void *)script, stackPos(0)); - return setGameFlag(stackPos(0)); -} - -int KyraEngine_v2::o2_setHandItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setHandItem(%p) (%d)", (const void *)script, stackPos(0)); - setHandItem(stackPos(0)); - return 0; -} - -int KyraEngine_v2::o2_removeHandItem(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_removeHandItem(%p) ()", (const void *)script); - removeHandItem(); - return 0; -} - -int KyraEngine_v2::o2_handItemSet(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_handItemSet(%p) ()", (const void *)script); - return _handItemSet; -} - -int KyraEngine_v2::o2_hideMouse(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_hideMouse(%p) ()", (const void *)script); - screen()->hideMouse(); - return 0; -} - int KyraEngine_v2::o2_addSpecialExit(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_addSpecialExit(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); @@ -155,18 +117,6 @@ int KyraEngine_v2::o2_addSpecialExit(EMCState *script) { return 0; } -int KyraEngine_v2::o2_setMousePos(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setMousePos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - setMousePos(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v2::o2_showMouse(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_showMouse(%p) ()", (const void *)script); - screen()->showMouse(); - return 0; -} - int KyraEngine_v2::o2_delay(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_delay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); if (stackPos(1)) { @@ -206,24 +156,6 @@ int KyraEngine_v2::o2_getShapeFlag1(EMCState *script) { return screen()->getShapeFlag1(stackPos(0), stackPos(1)); } -int KyraEngine_v2::o2_playWanderScoreViaMap(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_playWanderScoreViaMap(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - snd_playWanderScoreViaMap(stackPos(0), stackPos(1)); - return 0; -} - -int KyraEngine_v2::o2_getRand(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert(stackPos(0) < stackPos(1)); - return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); -} - -int KyraEngine_v2::o2_setDeathHandler(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setDeathHandler(%p) (%d)", (const void *)script, stackPos(0)); - _deathHandler = stackPos(0); - return 0; -} - int KyraEngine_v2::o2_waitForConfirmationClick(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_waitForConfirmationClick(%p) (%d)", (const void *)script, stackPos(0)); resetSkipFlag(); diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index ddd8beb5dc..73d69ef10c 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -40,7 +40,7 @@ namespace Kyra { -SeqPlayer::SeqPlayer(KyraEngine_v1 *vm, OSystem *system) { +SeqPlayer::SeqPlayer(KyraEngine_LoK *vm, OSystem *system) { _vm = vm; _system = system; @@ -110,7 +110,7 @@ void SeqPlayer::makeHandShapes() { } else { for (int i = 0; i < ARRAYSIZE(_handShapes); ++i) { if (_handShapes[i]) - delete [] _handShapes[i]; + delete[] _handShapes[i]; _handShapes[i] = setPanPages(3, i); assert(_handShapes[i]); } @@ -120,7 +120,7 @@ void SeqPlayer::makeHandShapes() { void SeqPlayer::freeHandShapes() { debugC(9, kDebugLevelSequence, "SeqPlayer::freeHandShapes()"); for (int i = 0; i < ARRAYSIZE(_handShapes); ++i) { - delete [] _handShapes[i]; + delete[] _handShapes[i]; _handShapes[i] = 0; } } @@ -262,7 +262,7 @@ void SeqPlayer::s1_loadPalette() { uint8 *srcData; srcData = _res->fileData(_vm->seqCOLTable()[colNum], &fileSize); memcpy(_screen->_currentPalette, srcData, fileSize); - delete [] srcData; + delete[] srcData; } } @@ -667,7 +667,7 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) { _screen->updateScreen(); } - delete [] _specialBuffer; + delete[] _specialBuffer; _specialBuffer = 0; return seqSkippedFlag; } diff --git a/engines/kyra/seqplayer.h b/engines/kyra/seqplayer.h index ce7f4648df..7e1b06d955 100644 --- a/engines/kyra/seqplayer.h +++ b/engines/kyra/seqplayer.h @@ -26,13 +26,13 @@ #ifndef KYRA_SEQPLAYER_H #define KYRA_SEQPLAYER_H -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" namespace Kyra { class SeqPlayer { public: - SeqPlayer(KyraEngine_v1 *vm, OSystem *system); + SeqPlayer(KyraEngine_LoK *vm, OSystem *system); ~SeqPlayer(); void setCopyViewOffs(bool offs) { @@ -46,7 +46,7 @@ public: uint8 *setPanPages(int pageNum, int shape); protected: - KyraEngine_v1 *_vm; + KyraEngine_LoK *_vm; OSystem *_system; Screen *_screen; Sound *_sound; diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 1c74f48990..169c319347 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -23,7 +23,7 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_hof.h" #include "kyra/screen.h" #include "kyra/wsamovie.h" @@ -231,7 +231,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqFrameDelay = cseq.frameDelay; _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; while (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { - uint32 starttime = _system->getMillis(); + _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); if (cb) (this->*cb)(0, 0, 0, 0); @@ -246,8 +246,8 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { if (now >= _seqEndTime && !_seqSubframePlaying) break; - uint32 tdiff = _seqEndTime - starttime; - int32 dly = _tickLength - (now - starttime); + uint32 tdiff = _seqEndTime - _seqSubFrameStartTime; + int32 dly = _tickLength - (now - _seqSubFrameStartTime); if (dly > 0) delay(MIN<uint32>(dly, tdiff)); } @@ -263,7 +263,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _seqEndTime = _system->getMillis() + dl; while (!((skipFlag() && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) { - uint32 starttime = _system->getMillis(); + _seqSubFrameStartTime = _system->getMillis(); seq_processWSAs(); _screen->copyPage(2, 0); @@ -275,8 +275,8 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { break; } - uint32 tdiff = _seqEndTime - starttime; - int32 dly = _tickLength - (now - starttime); + uint32 tdiff = _seqEndTime - _seqSubFrameStartTime; + int32 dly = _tickLength - (now - _seqSubFrameStartTime); if (dly > 0) delay(MIN<uint32>(dly, tdiff)); } @@ -284,13 +284,12 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_sequenceCommand(cseq.finalCommand); seq_resetAllTextEntries(); - if (_flags.isDemo && !_flags.isTalkie) { - if (seqNum == kSequenceDemoFisher) { - _abortIntroFlag = false; - resetSkipFlag(); - seqNum = kSequenceDemoVirgin; - } - } else { + if (_abortIntroFlag || skipFlag()) { + _sound->haltTrack(); + _sound->voiceStop(); + } + + if (!_flags.isDemo || _flags.isTalkie) { if ((seqNum != kSequenceTitle && seqNum < kSequenceZanfaun && (_abortIntroFlag || skipFlag())) || seqNum == kSequenceZanfaun) { _abortIntroFlag = false; @@ -301,6 +300,8 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _eventList.clear(); seqNum = kSequenceFirates; } + } else if (seqNum == kSequenceDemoFisher && !(_abortIntroFlag || skipFlag())) { + seqNum = kSequenceDemoVirgin; } if (_menuChoice) { @@ -314,8 +315,13 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { } } + if (_flags.isDemo && !_flags.isTalkie) { + _eventList.clear(); + _screen->fadeToBlack(); + } + if (!_menuChoice) - delay(1000); + delay(1200); _screen->setCurPage(oldPage); _screen->showMouse(); @@ -330,7 +336,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { seq_uninit(); } -int KyraEngine_HoF::seq_introWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::seq_introWestwood(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm); if (frm == -2) { @@ -343,7 +349,7 @@ int KyraEngine_HoF::seq_introWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_introTitle(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::seq_introTitle(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm); if (frm == 1) { @@ -365,18 +371,19 @@ int KyraEngine_HoF::seq_introTitle(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_introOverview(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::seq_introOverview(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm); uint8 *tmpPal = &(_screen->getPalette(3)[0x101]); memset(tmpPal, 0, 256); - uint32 endtime = 0, now = 0; + _seqSubFrameEndTimeInternal = 0; + uint32 now = 0; switch (_seqFrameCounter) { case 0: _seqSubframePlaying = true; _sound->playTrack(4); - endtime = _system->getMillis() + 60 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 60 * _tickLength; _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); @@ -385,8 +392,8 @@ int KyraEngine_HoF::seq_introOverview(WSAMovieV2 *wsaObj, int x, int y, int frm) _screen->setTextColorMap(_seqTextColorMap); now = _system->getMillis(); - if (endtime > now) - delay(endtime - now); + if (_seqSubFrameEndTimeInternal > now) + delay(_seqSubFrameEndTimeInternal - now); break; case 1: @@ -465,7 +472,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_introLibrary(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::seq_introLibrary(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm); switch (_seqFrameCounter) { @@ -541,7 +548,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovieV2 *wsaObj, int x, int y, int frm) } -int KyraEngine_HoF::seq_introHand(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { debugC(9, kDebugLevelMain, "KyraEngine_HoF::seq_introHand(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm); switch (_seqFrameCounter) { @@ -625,7 +632,7 @@ int KyraEngine_HoF::seq_introHand(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_introPoint(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == -2) { seq_waitForTextsTimeout(); _seqEndTime = 0; @@ -658,7 +665,7 @@ int KyraEngine_HoF::seq_introPoint(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_introZanfaun(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == -2) { seq_waitForTextsTimeout(); _seqEndTime = 0; @@ -747,7 +754,7 @@ int KyraEngine_HoF::seq_introZanfaun(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_introOver1(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introOver1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 2) seq_waitForTextsTimeout(); else if (frm == 3) @@ -756,13 +763,13 @@ int KyraEngine_HoF::seq_introOver1(WSAMovieV2 *wsaObj, int x, int y, int frm) { } -int KyraEngine_HoF::seq_introOver2(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introOver2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 1) seq_playTalkText(12); return frm; } -int KyraEngine_HoF::seq_introForest(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introForest(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 11) seq_waitForTextsTimeout(); else if (frm == 12) @@ -771,7 +778,7 @@ int KyraEngine_HoF::seq_introForest(WSAMovieV2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introDragon(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 11) seq_waitForTextsTimeout(); else if (frm == 3) @@ -779,17 +786,17 @@ int KyraEngine_HoF::seq_introDragon(WSAMovieV2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introDarm(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm) { //NULLSUB (at least in fm-towns version) return frm; } -int KyraEngine_HoF::seq_introLibrary2(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { //NULLSUB (at least in fm-towns version) return frm; } -int KyraEngine_HoF::seq_introMarco(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 36) { seq_waitForTextsTimeout(); _seqEndTime = 0; @@ -797,35 +804,35 @@ int KyraEngine_HoF::seq_introMarco(WSAMovieV2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introHand1a(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm) { //NULLSUB (at least in fm-towns version) return frm; } -int KyraEngine_HoF::seq_introHand1b(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introHand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 15) frm = 12; return frm; } -int KyraEngine_HoF::seq_introHand1c(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 8) frm = 4; return frm; } -int KyraEngine_HoF::seq_introHand2(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { //NULLSUB (at least in fm-towns version) return frm; } -int KyraEngine_HoF::seq_introHand3(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { //NULLSUB (at least in fm-towns version) return frm; } -int KyraEngine_HoF::seq_finaleFunters(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -846,12 +853,12 @@ int KyraEngine_HoF::seq_finaleFunters(WSAMovieV2 *wsaObj, int x, int y, int frm) _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(81, 240, 70, _seqTextColorMap, 252); seq_printCreditsString(82, 240, 90, _seqTextColorMap, _seqTextColor[0]); _screen->copyPage(2, 12); - delay(endtime - _system->getMillis()); seq_playTalkText(_flags.isTalkie ? 28 : 24); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqTextColor[0] = 1; if (_flags.isTalkie) { @@ -908,8 +915,8 @@ int KyraEngine_HoF::seq_finaleFunters(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_finaleFerb(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -920,7 +927,7 @@ int KyraEngine_HoF::seq_finaleFerb(WSAMovieV2 *wsaObj, int x, int y, int frm) { switch (frm) { case -2: seq_sequenceCommand(9); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(34, 240, _flags.isTalkie ? 60 : 40, _seqTextColorMap, 252); seq_printCreditsString(35, 240, _flags.isTalkie ? 70 : 50, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(36, 240, _flags.isTalkie ? 90 : 70, _seqTextColorMap, 252); @@ -929,7 +936,7 @@ int KyraEngine_HoF::seq_finaleFerb(WSAMovieV2 *wsaObj, int x, int y, int frm) { seq_printCreditsString(39, 240, _flags.isTalkie ? 130 : 120, _seqTextColorMap, _seqTextColor[0]); if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) seq_printCreditsString(103, 240, 130, _seqTextColorMap, _seqTextColor[0]); - delay(endtime - _system->getMillis()); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqEndTime = 0; break; @@ -992,8 +999,8 @@ int KyraEngine_HoF::seq_finaleFerb(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_finaleFish(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -1002,7 +1009,7 @@ int KyraEngine_HoF::seq_finaleFish(WSAMovieV2 *wsaObj, int x, int y, int frm) { switch (frm) { case -2: seq_sequenceCommand(9); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(40, 240, _flags.isTalkie ? 55 : 40, _seqTextColorMap, 252); seq_printCreditsString(41, 240, _flags.isTalkie ? 65 : 50, _seqTextColorMap, _seqTextColor[0]); @@ -1011,7 +1018,7 @@ int KyraEngine_HoF::seq_finaleFish(WSAMovieV2 *wsaObj, int x, int y, int frm) { seq_printCreditsString(44, 240, _flags.isTalkie ? 105 : 90, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(93, 240, _flags.isTalkie ? 125 : 110, _seqTextColorMap, 252); seq_printCreditsString(94, 240, _flags.isTalkie ? 135 : 120, _seqTextColorMap, _seqTextColor[0]); - delay(endtime - _system->getMillis()); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqEndTime = 0; break; @@ -1069,8 +1076,8 @@ int KyraEngine_HoF::seq_finaleFish(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_finaleFheep(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -1084,7 +1091,7 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovieV2 *wsaObj, int x, int y, int frm) { _screen->copyPage(2, 0); _screen->updateScreen(); seq_sequenceCommand(9); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(49, 240, 20, _seqTextColorMap, 252); seq_printCreditsString(50, 240, 30, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(51, 240, 40, _seqTextColorMap, _seqTextColor[0]); @@ -1101,7 +1108,7 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovieV2 *wsaObj, int x, int y, int frm) { seq_printCreditsString(63, 240, 150, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(64, 240, 160, _seqTextColorMap, _seqTextColor[0]); - delay(endtime - _system->getMillis()); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqEndTime = 0; break; @@ -1151,8 +1158,8 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_finaleFarmer(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -1164,7 +1171,7 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovieV2 *wsaObj, int x, int y, int frm) _screen->copyPage(2, 0); _screen->updateScreen(); seq_sequenceCommand(9); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(45, 240, 40, _seqTextColorMap, 252); seq_printCreditsString(46, 240, 50, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(47, 240, 60, _seqTextColorMap, _seqTextColor[0]); @@ -1177,7 +1184,7 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovieV2 *wsaObj, int x, int y, int frm) seq_printCreditsString(69, 240, 150, _seqTextColorMap, _seqTextColor[0]); if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) seq_printCreditsString(104, 240, 160, _seqTextColorMap, _seqTextColor[0]); - delay(endtime - _system->getMillis()); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqEndTime = 0; break; @@ -1221,8 +1228,8 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_finaleFuards(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -1235,7 +1242,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovieV2 *wsaObj, int x, int y, int frm) switch (frm) { case -2: seq_sequenceCommand(9); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(70, 240, 20, _seqTextColorMap, 252); seq_printCreditsString(71, 240, 30, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(72, 240, 40, _seqTextColorMap, _seqTextColor[0]); @@ -1250,7 +1257,7 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovieV2 *wsaObj, int x, int y, int frm) seq_printCreditsString(90, 240, 130, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(91, 240, 140, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(92, 240, 150, _seqTextColorMap, _seqTextColor[0]); - delay(endtime - _system->getMillis()); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqEndTime = 0; break; @@ -1321,8 +1328,8 @@ int KyraEngine_HoF::seq_finaleFuards(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_finaleFirates(WSAMovieV2 *wsaObj, int x, int y, int frm) { - uint32 endtime = 0; +int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + _seqSubFrameEndTimeInternal = 0; int chatX = 0; int chatY = 0; int chatW = 0; @@ -1334,7 +1341,7 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovieV2 *wsaObj, int x, int y, int frm) _screen->copyPage(2, 0); _screen->updateScreen(); seq_sequenceCommand(9); - endtime = _system->getMillis() + 480 * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; seq_printCreditsString(76, 240, 40, _seqTextColorMap, 252); seq_printCreditsString(77, 240, 50, _seqTextColorMap, 252); seq_printCreditsString(78, 240, 60, _seqTextColorMap, _seqTextColor[0]); @@ -1344,7 +1351,7 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovieV2 *wsaObj, int x, int y, int frm) seq_printCreditsString(85, 240, 110, _seqTextColorMap, _seqTextColor[0]); seq_printCreditsString(99, 240, 130, _seqTextColorMap, 252); seq_printCreditsString(100, 240, 140, _seqTextColorMap, _seqTextColor[0]); - delay(endtime - _system->getMillis()); + delay(_seqSubFrameEndTimeInternal - _system->getMillis()); _seqEndTime = 0; break; @@ -1413,7 +1420,7 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovieV2 *wsaObj, int x, int y, int frm) return 0; } -int KyraEngine_HoF::seq_finaleFrash(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm) { int tmp = 0; switch (frm) { @@ -1535,13 +1542,13 @@ void KyraEngine_HoF::seq_finaleActorScreen() { seq_displayScrollText(dataPtr, &d, 2, 6, 5, 1, Screen::FID_GOLDFONT_FNT, Screen::FID_GOLDFONT_FNT, 0, talkieCreditsSpecial); delay(120); - delete [] dataPtr; + delete[] dataPtr; _staticres->unloadId(k2SeqplayCreditsSpecial); _sound->setSoundList(&_soundData[kMusicFinale]); _sound->loadSoundFile(0); } -int KyraEngine_HoF::seq_finaleFiggle(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_finaleFiggle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (_seqFrameCounter == 10) _seqEndTime = 0; if (_seqFrameCounter == 10 || _seqFrameCounter == 5 || _seqFrameCounter == 7) @@ -1551,18 +1558,18 @@ int KyraEngine_HoF::seq_finaleFiggle(WSAMovieV2 *wsaObj, int x, int y, int frm) return frm; } -int KyraEngine_HoF::seq_demoVirgin(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoVirgin(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) delay(50 * _tickLength); return 0; } -int KyraEngine_HoF::seq_demoWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) _sound->playTrack(2); return 0; } -int KyraEngine_HoF::seq_demoTitle(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) { _sound->playTrack(3); } else if (frm == 25) { @@ -1573,7 +1580,7 @@ int KyraEngine_HoF::seq_demoTitle(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_demoHill(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoHill(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) { _sound->playTrack(4); } else if (frm == 25) { @@ -1593,7 +1600,7 @@ int KyraEngine_HoF::seq_demoHill(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_demoOuthome(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoOuthome(WSAMovie_v2 *wsaObj, int x, int y, int frm) { switch (frm) { case 12: seq_playTalkText(4); @@ -1634,7 +1641,7 @@ int KyraEngine_HoF::seq_demoOuthome(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_demoWharf(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoWharf(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!_seqFrameCounter) seq_loadNestedSequence(0, kSequenceDemoWharf2); @@ -1675,7 +1682,7 @@ int KyraEngine_HoF::seq_demoWharf(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_demoDinob(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoDinob(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 0) { if (!(_seqFrameCounter/8)) { seq_loadNestedSequence(0, kSequenceDemoDinob2); @@ -1696,7 +1703,7 @@ int KyraEngine_HoF::seq_demoDinob(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_demoFisher(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoFisher(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (((_system->getMillis() - _seqStartTime) / (5 * _tickLength)) > 0) { _seqStartTime = _system->getMillis(); if (!_seqFrameCounter) { @@ -1738,14 +1745,14 @@ int KyraEngine_HoF::seq_demoFisher(WSAMovieV2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_demoWharf2(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoWharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 69) _seqWsaCurrentFrame = 8; return frm; } -int KyraEngine_HoF::seq_demoDinob2(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoDinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { switch (frm) { case 19: seq_playTalkText(13); @@ -1775,17 +1782,17 @@ int KyraEngine_HoF::seq_demoDinob2(WSAMovieV2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_demoWater(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoWater(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 1) seq_playTalkText(11); return frm; } -int KyraEngine_HoF::seq_demoBail(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoBail(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_demoDig(WSAMovieV2 *wsaObj, int x, int y, int frm) { +int KyraEngine_HoF::seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } @@ -1806,7 +1813,7 @@ uint32 KyraEngine_HoF::seq_activeTextsTimeLeft() { } void KyraEngine_HoF::seq_processWSAs() { - for (int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { if (_activeWSA[i].flags != -1) { if (seq_processNextSubFrame(i)) seq_resetActiveWSA(i); @@ -2045,7 +2052,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { NestedSequence s = _sequences->seqn[seqNum]; if (!_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie = new WSAMovieV2(this, _screen); + _activeWSA[wsaNum].movie = new WSAMovie_v2(this, _screen); assert(_activeWSA[wsaNum].movie); } @@ -2325,17 +2332,20 @@ void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const _seqTextColor[0] = seqTextColor0; } -void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovieV2 *wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos) { +void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovie_v2 *wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos) { int dur = int(strlen(_sequenceStrings[strIndex])) * (_flags.isTalkie ? 7 : 15); int entry = textEnabled() ? seq_setTextEntry(strIndex, x, y, dur, width) : strIndex; _activeText[entry].textcolor = textColor; - uint32 chatTimeout = _system->getMillis() + dur * _tickLength; + _seqWsaChatTimeout = _system->getMillis() + dur * _tickLength; int curframe = firstframe; - if (vocIndex && speechEnabled()) + if (vocIndex && speechEnabled()) { + while (_sound->voiceIsPlaying() && !skipFlag()) + delay(4); seq_playTalkText(vocIndex); + } - while (_system->getMillis() < chatTimeout && !(_abortIntroFlag || skipFlag())) { + while (_system->getMillis() < _seqWsaChatTimeout && !(_abortIntroFlag || skipFlag())) { if (lastframe < 0) { int t = ABS(lastframe); if (t < curframe) @@ -2345,7 +2355,7 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i if (ABS(lastframe) < curframe) curframe = firstframe; - uint32 frameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; + _seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; if (wsa) { wsa->setDrawPage(2); wsa->setX(wsaXpos); @@ -2358,8 +2368,8 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i seq_processText(); uint32 tm = _system->getMillis(); - if (frameTimeout > tm && chatTimeout > tm) - delay(MIN(frameTimeout - tm, chatTimeout - tm)); + if (_seqWsaChatFrameTimeout > tm && _seqWsaChatTimeout > tm) + delay(MIN(_seqWsaChatFrameTimeout - tm, _seqWsaChatTimeout - tm)); if (speechEnabled() && !textEnabled() && !snd_voiceIsPlaying()) break; @@ -2372,11 +2382,8 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i if (_abortIntroFlag || skipFlag()) _sound->voiceStop(); - if (lastframe < 0) { - int t = ABS(lastframe); - if (t < curframe) - curframe = t; - } + if (ABS(lastframe) < curframe) + curframe = ABS(lastframe); if (curframe == firstframe) curframe++; @@ -2390,27 +2397,46 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int if (!data) return; - static const char mark[] = { 5, 13, 0}; + static const char mark[] = { 5, 13, 0 }; _screen->clearPage(tempPage1); _screen->clearPage(tempPage2); _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, 0, tempPage1); - uint8 *tmp = new uint8[397]; - memset(tmp, 0, 397); - uint8 **tmpStringTable = new uint8*[35]; + struct ScrollTextData { + int16 x; + int16 y; + uint8 *text; + byte unk1; + byte height; + byte adjust; + + ScrollTextData() { + x = 0; // 0 11 + y = 0; // 2 13 + text = 0; // 4 15 + unk1 = 0; // 8 19 + height = 0; // 9 20 + adjust = 0; // 10 21 + } + }; + + ScrollTextData *textData = new ScrollTextData[36]; uint8 *ptr = data; - int strTblIndex = 0; bool loop = true; int cnt = 0; while (loop) { - uint32 endTime = _system->getMillis() + speed * _tickLength; + _seqSubFrameEndTimeInternal = _system->getMillis() + speed * _tickLength; while (cnt < 35 && *ptr) { - int m = cnt * 11; - uint16 cH = cnt ? READ_LE_UINT16(&tmp[m + 2]) + tmp[m + 9] + (tmp[m + 9] >> 3) : d->h; + uint16 cH; + + if (cnt) + cH = textData[cnt].y + textData[cnt].height + (textData[cnt].height >> 3); + else + cH = d->h; char *str = (char*)ptr; @@ -2418,12 +2444,15 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int if (!ptr) ptr = (uint8*)strchr(str, 0); - tmp[m + 19] = *ptr; + textData[cnt + 1].unk1 = *ptr; *ptr = 0; - if (tmp[m + 19]) + if (textData[cnt + 1].unk1) ptr++; - tmp[m + 21] = (*str == 3 || *str == 4) ? tmp[m + 21] = *str++ : 0; + if (*str == 3 || *str == 4) + textData[cnt + 1].adjust = *str++; + else + textData[cnt + 1].adjust = 0; _screen->setFont(fid1); @@ -2434,18 +2463,25 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int str++; } - tmp[m + 20] = _screen->getFontHeight(); + textData[cnt + 1].height = _screen->getFontHeight(); - WRITE_LE_UINT16(&tmp[m + 11], (tmp[m + 21] == 3) ? 157 - _screen->getTextWidth(str) : - ((tmp[m + 21] == 4) ? 161 : (((d->w << 3) - _screen->getTextWidth(str)) >> 1) + 1)); + switch (textData[cnt + 1].adjust) { + case 3: + textData[cnt + 1].x = 157 - _screen->getTextWidth(str); + break; + case 4: + textData[cnt + 1].x = 161; + break; + default: + textData[cnt + 1].x = (((d->w << 3) - _screen->getTextWidth(str)) >> 1) + 1; + break; + } - if (tmp[m + 8] == 5) - cH -= (tmp[m + 9] + (tmp[m + 9] >> 3)); + if (textData[cnt].unk1 == 5) + cH -= (textData[cnt].height + (textData[cnt].height >> 3)); - WRITE_LE_UINT16(&tmp[m + 13], cH); - WRITE_LE_UINT32(&tmp[m + 15], strTblIndex); - tmpStringTable[strTblIndex] = (uint8*) str; - strTblIndex = (strTblIndex + 1) % 35; + textData[cnt + 1].y = cH; + textData[cnt + 1].text = (uint8*) str; cnt++; } @@ -2455,11 +2491,10 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int bool palCycle = 0; while (cnt2 < cnt) { - int m = cnt2 * 11; - const char *str = (const char*)tmpStringTable[READ_LE_UINT32(&tmp[m + 15])]; + const char *str = (const char*)textData[cnt2 + 1].text; const char *str2 = str; - uint16 cW = READ_LE_UINT16(&tmp[m + 11]) - 10; - uint16 cH = READ_LE_UINT16(&tmp[m + 13]); + int16 cW = textData[cnt2 + 1].x - 10; + int16 cH = textData[cnt2 + 1].y; int x = (d->sx << 3) + cW; int y = d->sy + cH; int col1 = 255; @@ -2467,7 +2502,7 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int if (cH < d->h) { _screen->setCurPage(tempPage2); _screen->setFont(fid1); - if (tmp[m + 20] != _screen->getFontHeight()) + if (textData[cnt2 + 1].height != _screen->getFontHeight()) _screen->setFont(fid2); if (specialData) { @@ -2498,18 +2533,18 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int _screen->setCurPage(0); } - WRITE_LE_UINT16(&tmp[m + 13], READ_LE_UINT16(&tmp[m + 13]) - step); + textData[cnt2 + 1].y -= step; cnt2++; } _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage2, 0); _screen->updateScreen(); - if ((int16)READ_LE_UINT16(&tmp[13]) < -10) { - tmpStringTable[tmp[15]] += strlen((char*)tmpStringTable[tmp[15]]); - tmpStringTable[tmp[15]][0] = tmp[19]; + if (textData[1].y < -10) { + textData[1].text += strlen((char*)textData[1].text); + textData[1].text[0] = textData[1].unk1; cnt--; - memcpy(&tmp[11], &tmp[22], cnt * 11); + memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); } if (palCycle) { @@ -2519,9 +2554,9 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int _screen->setScreenPalette(_screen->_currentPalette); } - delayUntil(endTime); + delayUntil(_seqSubFrameEndTimeInternal); - if ((cnt < 36) && ((d->sy + d->h) > (READ_LE_UINT16(&tmp[cnt * 11 + 2]) + tmp[cnt * 11 + 9])) && !skipFlag()) { + if ((cnt < 36) && ((d->sy + d->h) > (textData[cnt].y + textData[cnt].height)) && !skipFlag()) { resetSkipFlag(); delay(_tickLength * 500); cnt = 0; @@ -2537,8 +2572,7 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int _abortIntroFlag= false; resetSkipFlag(); - delete [] tmp; - delete [] tmpStringTable; + delete[] textData; } void KyraEngine_HoF::seq_scrollPage() { @@ -2571,7 +2605,7 @@ void KyraEngine_HoF::seq_scrollPage() { } void KyraEngine_HoF::seq_showStarcraftLogo() { - WSAMovieV2 *ci = new WSAMovieV2(this, _screen); + WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen); assert(ci); _screen->clearPage(2); _res->loadPakFile("INTROGEN.PAK"); @@ -2589,20 +2623,20 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { _screen->copyPage(2, 0); _screen->fadeFromBlack(); for (int i = 1; i < endframe; i++) { - uint32 endTime = _system->getMillis() + 50; + _seqEndTime = _system->getMillis() + 50; if (skipFlag()) break; ci->displayFrame(i, 0); _screen->copyPage(2, 0); _screen->updateScreen(); - delay(endTime - _system->getMillis()); + delay(_seqEndTime - _system->getMillis()); } if(!skipFlag()) { - uint32 endTime = _system->getMillis() + 50; + _seqEndTime = _system->getMillis() + 50; ci->displayFrame(0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); - delay(endTime - _system->getMillis()); + delay(_seqEndTime - _system->getMillis()); } _screen->fadeToBlack(); _screen->showMouse(); @@ -2613,7 +2647,7 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { void KyraEngine_HoF::seq_init() { _seqProcessedString = new char[200]; - _seqWsa = new WSAMovieV2(this, _screen); + _seqWsa = new WSAMovie_v2(this, _screen); _activeWSA = new ActiveWSA[8]; _activeText = new ActiveText[10]; @@ -2623,12 +2657,12 @@ void KyraEngine_HoF::seq_init() { int numShp = -1; if (_flags.isDemo && !_flags.isTalkie) { - _demoAnimData = _staticres->loadHofShapeAnimDataV1(k2SeqplayShapeAnimData, _itemAnimDataSize); + _demoAnimData = _staticres->loadShapeAnimData_v1(k2SeqplayShapeAnimData, _itemAnimDataSize); uint8 *shp = _res->fileData("icons.shp", 0); uint32 outsize = READ_LE_UINT16(shp + 4); _animShapeFiledata = new uint8[outsize]; Screen::decodeFrame4(shp + 10, _animShapeFiledata, outsize); - delete [] shp; + delete[] shp; do { numShp++; @@ -2647,26 +2681,24 @@ void KyraEngine_HoF::seq_init() { } void KyraEngine_HoF::seq_uninit() { - delete [] _seqProcessedString; + delete[] _seqProcessedString; _seqProcessedString = NULL; - delete [] _activeWSA; + delete[] _activeWSA; _activeWSA = NULL; - delete [] _activeText; + delete[] _activeText; _activeText = NULL; delete _seqWsa; _seqWsa = NULL; - delete [] _animShapeFiledata; + delete[] _animShapeFiledata; _animShapeFiledata = 0; if (_flags.isDemo && !_flags.isTalkie) _staticres->unloadId(k2SeqplayShapeAnimData); - _gameShapes.clear(); - delete _menu; _menu = 0; } @@ -2772,7 +2804,7 @@ void KyraEngine_HoF::seq_makeBookAppear() { } closeInvWsa(); - delete [] rect; + delete[] rect; _invWsa.running = false; _screen->showMouse(); @@ -2780,3 +2812,4 @@ void KyraEngine_HoF::seq_makeBookAppear() { } // end of namespace Kyra + diff --git a/engines/kyra/sequences_v1.cpp b/engines/kyra/sequences_lok.cpp index 01906d2529..b30568c7e2 100644 --- a/engines/kyra/sequences_v1.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -23,14 +23,14 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_lok.h" #include "kyra/seqplayer.h" -#include "kyra/screen_v1.h" +#include "kyra/screen_lok.h" #include "kyra/resource.h" #include "kyra/sound.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" #include "kyra/text.h" #include "kyra/timer.h" @@ -40,8 +40,8 @@ namespace Kyra { -void KyraEngine_v1::seq_demo() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_demo()"); +void KyraEngine_LoK::seq_demo() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_demo()"); snd_playTheme(0, 2); @@ -90,18 +90,18 @@ void KyraEngine_v1::seq_demo() { _sound->haltTrack(); } -void KyraEngine_v1::seq_intro() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_intro()"); +void KyraEngine_LoK::seq_intro() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_intro()"); if (_flags.isTalkie) _res->loadPakFile("INTRO.VRM"); static const IntroProc introProcTable[] = { - &KyraEngine_v1::seq_introLogos, - &KyraEngine_v1::seq_introStory, - &KyraEngine_v1::seq_introMalcolmTree, - &KyraEngine_v1::seq_introKallakWriting, - &KyraEngine_v1::seq_introKallakMalcolm + &KyraEngine_LoK::seq_introLogos, + &KyraEngine_LoK::seq_introStory, + &KyraEngine_LoK::seq_introMalcolmTree, + &KyraEngine_LoK::seq_introKallakWriting, + &KyraEngine_LoK::seq_introKallakMalcolm }; Common::InSaveFile *in; @@ -130,8 +130,8 @@ void KyraEngine_v1::seq_intro() { _res->unloadPakFile("INTRO.VRM"); } -void KyraEngine_v1::seq_introLogos() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introLogos()"); +void KyraEngine_LoK::seq_introLogos() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_introLogos()"); if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { _screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette); @@ -176,7 +176,7 @@ void KyraEngine_v1::seq_introLogos() { _screen->setScreenPalette(_screen->_currentPalette); } - if (_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence() || _quitFlag) { + if ((_seq->playSequence(_seq_KyrandiaLogo, _skipFlag) && !seq_skipSequence()) || _quitFlag) { _screen->fadeToBlack(); _screen->clearPage(0); return; @@ -232,8 +232,8 @@ void KyraEngine_v1::seq_introLogos() { _seq->playSequence(_seq_Forest, true); } -void KyraEngine_v1::seq_introStory() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introStory()"); +void KyraEngine_LoK::seq_introStory() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_introStory()"); _screen->clearPage(3); _screen->clearPage(0); @@ -279,15 +279,15 @@ void KyraEngine_v1::seq_introStory() { delay(360 * _tickLength); } -void KyraEngine_v1::seq_introMalcolmTree() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introMalcolmTree()"); +void KyraEngine_LoK::seq_introMalcolmTree() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_introMalcolmTree()"); _screen->_curPage = 0; _screen->clearPage(3); _seq->playSequence(_seq_MalcolmTree, true); } -void KyraEngine_v1::seq_introKallakWriting() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introKallakWriting()"); +void KyraEngine_LoK::seq_introKallakWriting() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_introKallakWriting()"); _seq->makeHandShapes(); _screen->setAnimBlockPtr(5060); _screen->_charWidth = -2; @@ -295,13 +295,13 @@ void KyraEngine_v1::seq_introKallakWriting() { _seq->playSequence(_seq_KallakWriting, true); } -void KyraEngine_v1::seq_introKallakMalcolm() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introKallakMalcolm()"); +void KyraEngine_LoK::seq_introKallakMalcolm() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_introKallakMalcolm()"); _screen->clearPage(3); _seq->playSequence(_seq_KallakMalcolm, true); } -void KyraEngine_v1::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) { +void KyraEngine_LoK::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) { debugC(9, kDebugLevelMain, "seq_createAmuletJewel(%d, %d, %d, %d)", jewel, page, noSound, drawOnly); static const uint16 specialJewelTable[] = { 0x167, 0x162, 0x15D, 0x158, 0x153, 0xFFFF @@ -361,7 +361,7 @@ void KyraEngine_v1::seq_createAmuletJewel(int jewel, int page, int noSound, int setGameFlag(0x55+jewel); } -void KyraEngine_v1::seq_brandonHealing() { +void KyraEngine_LoK::seq_brandonHealing() { debugC(9, kDebugLevelMain, "seq_brandonHealing()"); if (!(_deathHandler & 8)) return; @@ -392,7 +392,7 @@ void KyraEngine_v1::seq_brandonHealing() { _screen->showMouse(); } -void KyraEngine_v1::seq_brandonHealing2() { +void KyraEngine_LoK::seq_brandonHealing2() { debugC(9, kDebugLevelMain, "seq_brandonHealing2()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -416,7 +416,7 @@ void KyraEngine_v1::seq_brandonHealing2() { characterSays(2011, _poisonGone[1], 0, -2); } -void KyraEngine_v1::seq_poisonDeathNow(int now) { +void KyraEngine_LoK::seq_poisonDeathNow(int now) { debugC(9, kDebugLevelMain, "seq_poisonDeathNow(%d)", now); if (!(_brandonStatusBit & 1)) return; @@ -437,7 +437,7 @@ void KyraEngine_v1::seq_poisonDeathNow(int now) { } } -void KyraEngine_v1::seq_poisonDeathNowAnim() { +void KyraEngine_LoK::seq_poisonDeathNowAnim() { debugC(9, kDebugLevelMain, "seq_poisonDeathNowAnim()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -478,7 +478,7 @@ void KyraEngine_v1::seq_poisonDeathNowAnim() { _screen->showMouse(); } -void KyraEngine_v1::seq_playFluteAnimation() { +void KyraEngine_LoK::seq_playFluteAnimation() { debugC(9, kDebugLevelMain, "seq_playFluteAnimation()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -532,7 +532,7 @@ void KyraEngine_v1::seq_playFluteAnimation() { } } -void KyraEngine_v1::seq_winterScroll1() { +void KyraEngine_LoK::seq_winterScroll1() { debugC(9, kDebugLevelMain, "seq_winterScroll1()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -613,7 +613,7 @@ void KyraEngine_v1::seq_winterScroll1() { _screen->showMouse(); } -void KyraEngine_v1::seq_winterScroll2() { +void KyraEngine_LoK::seq_winterScroll2() { debugC(9, kDebugLevelMain, "seq_winterScroll2()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -642,7 +642,7 @@ void KyraEngine_v1::seq_winterScroll2() { _screen->showMouse(); } -void KyraEngine_v1::seq_makeBrandonInv() { +void KyraEngine_LoK::seq_makeBrandonInv() { debugC(9, kDebugLevelMain, "seq_makeBrandonInv()"); if (_deathHandler == 8) return; @@ -668,7 +668,7 @@ void KyraEngine_v1::seq_makeBrandonInv() { _screen->showMouse(); } -void KyraEngine_v1::seq_makeBrandonNormal() { +void KyraEngine_LoK::seq_makeBrandonNormal() { debugC(9, kDebugLevelMain, "seq_makeBrandonNormal()"); _screen->hideMouse(); _brandonStatusBit |= 0x40; @@ -684,7 +684,7 @@ void KyraEngine_v1::seq_makeBrandonNormal() { _screen->showMouse(); } -void KyraEngine_v1::seq_makeBrandonNormal2() { +void KyraEngine_LoK::seq_makeBrandonNormal2() { debugC(9, kDebugLevelMain, "seq_makeBrandonNormal2()"); _screen->hideMouse(); assert(_brandonToWispTable); @@ -710,7 +710,7 @@ void KyraEngine_v1::seq_makeBrandonNormal2() { _screen->showMouse(); } -void KyraEngine_v1::seq_makeBrandonWisp() { +void KyraEngine_LoK::seq_makeBrandonWisp() { debugC(9, kDebugLevelMain, "seq_makeBrandonWisp()"); if (_deathHandler == 8) return; @@ -752,7 +752,7 @@ void KyraEngine_v1::seq_makeBrandonWisp() { _screen->showMouse(); } -void KyraEngine_v1::seq_dispelMagicAnimation() { +void KyraEngine_LoK::seq_dispelMagicAnimation() { debugC(9, kDebugLevelMain, "seq_dispelMagicAnimation()"); if (_deathHandler == 8) return; @@ -794,7 +794,7 @@ void KyraEngine_v1::seq_dispelMagicAnimation() { _screen->showMouse(); } -void KyraEngine_v1::seq_fillFlaskWithWater(int item, int type) { +void KyraEngine_LoK::seq_fillFlaskWithWater(int item, int type) { debugC(9, kDebugLevelMain, "seq_fillFlaskWithWater(%d, %d)", item, type); int newItem = -1; static const uint8 flaskTable1[] = { 0x46, 0x48, 0x4A, 0x4C }; @@ -827,8 +827,8 @@ void KyraEngine_v1::seq_fillFlaskWithWater(int item, int type) { characterSays(voiceEntries[type], _fullFlask[type], 0, -2); } -void KyraEngine_v1::seq_playDrinkPotionAnim(int item, int unk2, int flags) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playDrinkPotionAnim(%d, %d, %d)", item, unk2, flags); +void KyraEngine_LoK::seq_playDrinkPotionAnim(int item, int unk2, int flags) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playDrinkPotionAnim(%d, %d, %d)", item, unk2, flags); uint8 red, green, blue; switch (item) { @@ -919,8 +919,8 @@ void KyraEngine_v1::seq_playDrinkPotionAnim(int item, int unk2, int flags) { _screen->showMouse(); } -int KyraEngine_v1::seq_playEnd() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playEnd()"); +int KyraEngine_LoK::seq_playEnd() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playEnd()"); if (_endSequenceSkipFlag) return 0; @@ -931,13 +931,13 @@ int KyraEngine_v1::seq_playEnd() { if (_endSequenceNeedLoading) { snd_playWanderScoreViaMap(50, 1); setupPanPages(); - _finalA = new WSAMovieV1(this); + _finalA = new WSAMovie_v1(this); assert(_finalA); _finalA->open("finala.wsa", 1, 0); - _finalB = new WSAMovieV1(this); + _finalB = new WSAMovie_v1(this); assert(_finalB); _finalB->open("finalb.wsa", 1, 0); - _finalC = new WSAMovieV1(this); + _finalC = new WSAMovie_v1(this); assert(_finalC); _endSequenceNeedLoading = 0; _finalC->open("finalc.wsa", 1, 0); @@ -981,7 +981,7 @@ int KyraEngine_v1::seq_playEnd() { _screen->setScreenPalette(_screen->_currentPalette); _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0); uint32 nextTime = _system->getMillis() + 120 * _tickLength; - _finalA = new WSAMovieV1(this); + _finalA = new WSAMovie_v1(this); assert(_finalA); _finalA->open("finald.wsa", 1, 0); _finalA->setX(8); _finalA->setY(8); @@ -1012,8 +1012,8 @@ int KyraEngine_v1::seq_playEnd() { return 0; } -void KyraEngine_v1::seq_brandonToStone() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_brandonToStone()"); +void KyraEngine_LoK::seq_brandonToStone() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_brandonToStone()"); _screen->hideMouse(); assert(_brandonStoneTable); setupShapes123(_brandonStoneTable, 14, 0); @@ -1028,8 +1028,8 @@ void KyraEngine_v1::seq_brandonToStone() { _screen->showMouse(); } -void KyraEngine_v1::seq_playEnding() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playEnding()"); +void KyraEngine_LoK::seq_playEnding() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playEnding()"); if (_quitFlag) return; _screen->hideMouse(); @@ -1052,8 +1052,8 @@ void KyraEngine_v1::seq_playEnding() { seq_playCredits(); } -void KyraEngine_v1::seq_playCredits() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playCredits()"); +void KyraEngine_LoK::seq_playCredits() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_playCredits()"); static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char stringTerms[] = { 0x5, 0xd, 0x0}; static const int numStrings = 250; @@ -1091,12 +1091,12 @@ void KyraEngine_v1::seq_playCredits() { if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { int sizeTmp = 0; - const uint8 *bufferTmp = _staticres->loadRawData(kCreditsStrings, sizeTmp); + const uint8 *bufferTmp = _staticres->loadRawData(k1CreditsStrings, sizeTmp); buffer = new uint8[sizeTmp]; assert(buffer); memcpy(buffer, bufferTmp, sizeTmp); size = sizeTmp; - _staticres->unloadId(kCreditsStrings); + _staticres->unloadId(k1CreditsStrings); } else { buffer = _res->fileData("CREDITS.TXT", &size); assert(buffer); @@ -1202,20 +1202,20 @@ void KyraEngine_v1::seq_playCredits() { _system->delayMillis(nextLoop - now); } - delete [] buffer; + delete[] buffer; _screen->fadeToBlack(); _screen->clearCurPage(); _screen->showMouse(); } -bool KyraEngine_v1::seq_skipSequence() const { - debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_skipSequence()"); +bool KyraEngine_LoK::seq_skipSequence() const { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::seq_skipSequence()"); return _quitFlag || _abortIntroFlag; } -int KyraEngine_v1::handleMalcolmFlag() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::handleMalcolmFlag()"); +int KyraEngine_LoK::handleMalcolmFlag() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::handleMalcolmFlag()"); static uint16 frame = 0; static uint32 timer1 = 0; static uint32 timer2 = 0; @@ -1383,8 +1383,8 @@ int KyraEngine_v1::handleMalcolmFlag() { return 0; } -int KyraEngine_v1::handleBeadState() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::handleBeadState()"); +int KyraEngine_LoK::handleBeadState() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::handleBeadState()"); static uint32 timer1 = 0; static uint32 timer2 = 0; static BeadState beadState1 = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1603,8 +1603,8 @@ int KyraEngine_v1::handleBeadState() { return 0; } -void KyraEngine_v1::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::initBeadState(%d, %d, %d, %d, %d, %p)", x, y, x2, y2, unk, (const void *)ptr); +void KyraEngine_LoK::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::initBeadState(%d, %d, %d, %d, %d, %p)", x, y, x2, y2, unk, (const void *)ptr); ptr->unk9 = unk; int xDiff = x2 - x; int yDiff = y2 - y; @@ -1637,8 +1637,8 @@ void KyraEngine_v1::initBeadState(int x, int y, int x2, int y2, int unk, BeadSta ptr->unk8 = unk2; } -int KyraEngine_v1::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::processBead(%d, %d, %p, %p, %p)", x, y, (const void *)&x2, (const void *)&y2, (const void *)ptr); +int KyraEngine_LoK::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::processBead(%d, %d, %p, %p, %p)", x, y, (const void *)&x2, (const void *)&y2, (const void *)ptr); if (x == ptr->dstX && y == ptr->dstY) return 1; @@ -1674,21 +1674,21 @@ int KyraEngine_v1::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) { return 0; } -void KyraEngine_v1::setupPanPages() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::setupPanPages()"); +void KyraEngine_LoK::setupPanPages() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::setupPanPages()"); _screen->savePageToDisk("BKGD.PG", 2); _screen->loadBitmap("BEAD.CPS", 3, 3, 0); if (_flags.platform == Common::kPlatformMacintosh || _flags.platform == Common::kPlatformAmiga) { int pageBackUp = _screen->_curPage; _screen->_curPage = 2; - delete [] _panPagesTable[19]; + delete[] _panPagesTable[19]; _panPagesTable[19] = _screen->encodeShape(0, 0, 16, 9, 0); assert(_panPagesTable[19]); int curX = 16; for (int i = 0; i < 19; ++i) { - delete [] _panPagesTable[i]; + delete[] _panPagesTable[i]; _panPagesTable[i] = _screen->encodeShape(curX, 0, 8, 5, 0); assert(_panPagesTable[i]); curX += 8; @@ -1697,7 +1697,7 @@ void KyraEngine_v1::setupPanPages() { _screen->_curPage = pageBackUp; } else { for (int i = 0; i <= 19; ++i) { - delete [] _panPagesTable[i]; + delete[] _panPagesTable[i]; _panPagesTable[i] = _seq->setPanPages(3, i); assert(_panPagesTable[i]); } @@ -1705,18 +1705,18 @@ void KyraEngine_v1::setupPanPages() { _screen->loadPageFromDisk("BKGD.PG", 2); } -void KyraEngine_v1::freePanPages() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::freePanPages()"); +void KyraEngine_LoK::freePanPages() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::freePanPages()"); delete _endSequenceBackUpRect; _endSequenceBackUpRect = 0; for (int i = 0; i <= 19; ++i) { - delete [] _panPagesTable[i]; + delete[] _panPagesTable[i]; _panPagesTable[i] = 0; } } -void KyraEngine_v1::closeFinalWsa() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::closeFinalWsa()"); +void KyraEngine_LoK::closeFinalWsa() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::closeFinalWsa()"); delete _finalA; _finalA = 0; delete _finalB; @@ -1727,7 +1727,7 @@ void KyraEngine_v1::closeFinalWsa() { _endSequenceNeedLoading = 1; } -void KyraEngine_v1::updateKyragemFading() { +void KyraEngine_LoK::updateKyragemFading() { static const uint8 kyraGemPalette[0x28] = { 0x3F, 0x3B, 0x38, 0x34, 0x32, 0x2F, 0x2C, 0x29, 0x25, 0x22, 0x1F, 0x1C, 0x19, 0x16, 0x12, 0x0F, 0x0C, 0x0A, 0x06, 0x03, @@ -1797,8 +1797,8 @@ void KyraEngine_v1::updateKyragemFading() { _kyragemFadingState.timerCount = _system->getMillis() + 120 * _tickLength; } -void KyraEngine_v1::drawJewelPress(int jewel, int drawSpecial) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelPress(%d, %d)", jewel, drawSpecial); +void KyraEngine_LoK::drawJewelPress(int jewel, int drawSpecial) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::drawJewelPress(%d, %d)", jewel, drawSpecial); _screen->hideMouse(); int shape = 0; @@ -1822,8 +1822,8 @@ void KyraEngine_v1::drawJewelPress(int jewel, int drawSpecial) { _screen->showMouse(); } -void KyraEngine_v1::drawJewelsFadeOutStart() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelsFadeOutStart()"); +void KyraEngine_LoK::drawJewelsFadeOutStart() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::drawJewelsFadeOutStart()"); static const uint16 jewelTable1[] = { 0x164, 0x15F, 0x15A, 0x155, 0x150, 0xFFFF }; static const uint16 jewelTable2[] = { 0x163, 0x15E, 0x159, 0x154, 0x14F, 0xFFFF }; static const uint16 jewelTable3[] = { 0x166, 0x160, 0x15C, 0x157, 0x152, 0xFFFF }; @@ -1842,8 +1842,8 @@ void KyraEngine_v1::drawJewelsFadeOutStart() { } } -void KyraEngine_v1::drawJewelsFadeOutEnd(int jewel) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelsFadeOutEnd(%d)", jewel); +void KyraEngine_LoK::drawJewelsFadeOutEnd(int jewel) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::drawJewelsFadeOutEnd(%d)", jewel); static const uint16 jewelTable[] = { 0x153, 0x158, 0x15D, 0x162, 0x148, 0xFFFF }; int newDelay = 0; diff --git a/engines/kyra/sequences_mr.cpp b/engines/kyra/sequences_mr.cpp index 8c826e2048..f41ed9c2f3 100644 --- a/engines/kyra/sequences_mr.cpp +++ b/engines/kyra/sequences_mr.cpp @@ -241,7 +241,7 @@ void KyraEngine_MR::uninitAnimationShapes(int count, uint8 *filedata) { debugC(9, kDebugLevelAnimator, "KyraEngine_MR::uninitAnimationShapes(%d, %p)", count, (const void*)filedata); for (int i = 0; i < count; ++i) _gameShapes[9+i] = 0; - delete [] filedata; + delete[] filedata; setNextIdleAnimTimer(); } diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp index aef510a616..cc4b8528a4 100644 --- a/engines/kyra/sequences_v2.cpp +++ b/engines/kyra/sequences_v2.cpp @@ -102,17 +102,14 @@ void KyraEngine_v2::processAnimationScript(int allowSkip, int resetChar) { uint32 delayEnd = _system->getMillis() + _animDelayTime * _tickLength; - while ((!skipFlag() || !allowSkip) && _system->getMillis() < delayEnd) { - if (_chatText) - updateWithText(); - else - update(); + while ((!skipFlag() || !allowSkip) && _system->getMillis() < delayEnd) + delay(10, true); - delay(10); - } - - if (skipFlag()) + if (skipFlag()) { resetSkipFlag(); + if (allowSkip) + break; + } } if (resetChar) { diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 887e9c7267..f56c43aabd 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -40,7 +40,7 @@ namespace Kyra { -Sound::Sound(KyraEngine *vm, Audio::Mixer *mixer) +Sound::Sound(KyraEngine_v1 *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _soundChannels(), _musicEnabled(1), _sfxEnabled(true), _soundDataList(0) { } @@ -50,9 +50,9 @@ Sound::~Sound() { bool Sound::voiceFileIsPresent(const char *file) { char filenamebuffer[25]; - for (int i = 0; _supportedCodes[i].fileext; ++i) { + for (int i = 0; _supportedCodecs[i].fileext; ++i) { strcpy(filenamebuffer, file); - strcat(filenamebuffer, _supportedCodes[i].fileext); + strcat(filenamebuffer, _supportedCodecs[i].fileext); if (_vm->resource()->getFileSize(filenamebuffer) > 0) return true; } @@ -66,51 +66,48 @@ bool Sound::voiceFileIsPresent(const char *file) { return false; } -bool Sound::voicePlay(const char *file, bool isSfx) { - uint32 fileSize = 0; - byte *fileData = 0; - bool found = false; +int32 Sound::voicePlay(const char *file, bool isSfx) { char filenamebuffer[25]; int h = 0; while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return false; + return 0; Audio::AudioStream *audioStream = 0; - for (int i = 0; _supportedCodes[i].fileext; ++i) { + for (int i = 0; _supportedCodecs[i].fileext; ++i) { strcpy(filenamebuffer, file); - strcat(filenamebuffer, _supportedCodes[i].fileext); + strcat(filenamebuffer, _supportedCodecs[i].fileext); Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filenamebuffer); if (!stream) continue; - audioStream = _supportedCodes[i].streamFunc(stream, true, 0, 0, 1); - found = true; + audioStream = _supportedCodecs[i].streamFunc(stream, true, 0, 0, 1); break; } - if (!found) { + if (!audioStream) { strcpy(filenamebuffer, file); strcat(filenamebuffer, ".VOC"); - fileData = _vm->resource()->fileData(filenamebuffer, &fileSize); + uint32 fileSize = 0; + byte *fileData = _vm->resource()->fileData(filenamebuffer, &fileSize); if (!fileData) - return false; + return 0; Common::MemoryReadStream vocStream(fileData, fileSize); audioStream = Audio::makeVOCStream(vocStream); + + delete[] fileData; + fileSize = 0; } _soundChannels[h].file = file; _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, audioStream); - delete [] fileData; - fileSize = 0; - - return true; + return audioStream->getTotalPlayTime(); } void Sound::voiceStop(const char *file) { @@ -143,9 +140,21 @@ bool Sound::voiceIsPlaying(const char *file) { return res; } +uint32 Sound::voicePlayedTime(const char *file) { + if (!file) + return 0; + + for (int i = 0; i < kNumChannelHandles; ++i) { + if (_soundChannels[i].file == file) + return _mixer->getSoundElapsedTime(_soundChannels[i].channelHandle); + } + + return 0; +} + #pragma mark - -SoundMidiPC::SoundMidiPC(KyraEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : Sound(vm, mixer) { +SoundMidiPC::SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *driver) : Sound(vm, mixer) { _driver = driver; _passThrough = false; @@ -320,7 +329,7 @@ void SoundMidiPC::metaEvent(byte type, byte *data, uint16 length) { struct DeleterArray { void operator ()(byte *ptr) { - delete [] ptr; + delete[] ptr; } }; @@ -467,8 +476,8 @@ void SoundMidiPC::beginFadeOut() { #pragma mark - -void KyraEngine::snd_playTheme(int file, int track) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playTheme(%d, %d)", file, track); +void KyraEngine_v1::snd_playTheme(int file, int track) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playTheme(%d, %d)", file, track); if (_curMusicTheme == file) return; @@ -478,13 +487,13 @@ void KyraEngine::snd_playTheme(int file, int track) { _sound->playTrack(track); } -void KyraEngine::snd_playSoundEffect(int track, int volume) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playSoundEffect(%d, %d)", track, volume); +void KyraEngine_v1::snd_playSoundEffect(int track, int volume) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playSoundEffect(%d, %d)", track, volume); _sound->playSoundEffect(track); } -void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playWanderScoreViaMap(%d, %d)", command, restart); +void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playWanderScoreViaMap(%d, %d)", command, restart); if (restart) _lastMusicCommand = -1; @@ -527,19 +536,22 @@ void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) { _lastMusicCommand = command; } -void KyraEngine::snd_stopVoice() { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_stopVoice()"); - _sound->voiceStop(_speechFile.empty() ? 0 : _speechFile.c_str()); +void KyraEngine_v1::snd_stopVoice() { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_stopVoice()"); + if (!_speechFile.empty()) { + _sound->voiceStop(_speechFile.c_str()); + _speechFile.clear(); + } } -bool KyraEngine::snd_voiceIsPlaying() { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceIsPlaying()"); - return _sound->voiceIsPlaying(_speechFile.empty() ? 0 : _speechFile.c_str()); +bool KyraEngine_v1::snd_voiceIsPlaying() { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_voiceIsPlaying()"); + return _speechFile.empty() ? false : _sound->voiceIsPlaying(_speechFile.c_str()); } // static res -const Sound::SpeechCodecs Sound::_supportedCodes[] = { +const Sound::SpeechCodecs Sound::_supportedCodecs[] = { #ifdef USE_FLAC { ".VOF", Audio::makeFlacStream }, #endif // USE_FLAC diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 85648f6b7e..1baeb3064a 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * LPGL License + * LGPL License * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -42,7 +42,7 @@ #ifndef KYRA_SOUND_H #define KYRA_SOUND_H -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "common/scummsys.h" #include "common/file.h" @@ -61,12 +61,12 @@ namespace Kyra { /** * Analog audio output device API for Kyrandia games. - * It countains functionallity to play music tracks, + * It contains functionality to play music tracks, * sound effects and voices. */ class Sound { public: - Sound(KyraEngine *vm, Audio::Mixer *mixer); + Sound(KyraEngine_v1 *vm, Audio::Mixer *mixer); virtual ~Sound(); enum kType { @@ -92,7 +92,7 @@ public: virtual void process() {} /** - * Updates internal volume settings according to ConfigManager + * Updates internal volume settings according to ConfigManager. */ virtual void updateVolumeSettings() {} @@ -105,7 +105,7 @@ public: virtual void setSoundList(const AudioDataStruct *list) { _soundDataList = list; } /** - * Checks if a given sound file is present + * Checks if a given sound file is present. * * @param track track number * @return true if available, false otherwise @@ -126,19 +126,19 @@ public: virtual void playTrack(uint8 track) = 0; /** - * Stop playback of the current track + * Stop playback of the current track. */ virtual void haltTrack() = 0; /** - * Plays the specified sound effect + * Plays the specified sound effect. * * @param track sound effect id */ virtual void playSoundEffect(uint8 track) = 0; /** - * Checks if the sound driver plays any sound + * Checks if the sound driver plays any sound. * * @return true if playing, false otherwise */ @@ -174,9 +174,9 @@ public: * * @param file file to be played * @param isSfx marks file as sfx instead of voice - * @return channel the voice file is played on + * @return playtime of the voice file (-1 marks unknown playtime) */ - virtual bool voicePlay(const char *file, bool isSfx = false); + virtual int32 voicePlay(const char *file, bool isSfx = false); /** * Checks if a voice is being played. @@ -186,13 +186,20 @@ public: bool voiceIsPlaying(const char *file = 0); /** + * Checks how long a voice has been playing + * + * @return time in milliseconds + */ + uint32 voicePlayedTime(const char *file); + + /** * Stops playback of the current voice. */ void voiceStop(const char *file = 0); protected: const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->_fileListLen) ? _soundDataList->_fileList[file] : ""; } const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; } - const int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; } + int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; } enum { kNumChannelHandles = 4 @@ -209,7 +216,7 @@ protected: int _currentTheme; - KyraEngine *_vm; + KyraEngine_v1 *_vm; Audio::Mixer *_mixer; private: @@ -225,7 +232,7 @@ private: uint numLoops); }; - static const SpeechCodecs _supportedCodes[]; + static const SpeechCodecs _supportedCodecs[]; }; class AdlibDriver; @@ -243,7 +250,7 @@ class AdlibDriver; */ class SoundAdlibPC : public Sound { public: - SoundAdlibPC(KyraEngine *vm, Audio::Mixer *mixer); + SoundAdlibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer); ~SoundAdlibPC(); kType getMusicType() const { return kAdlib; } @@ -298,7 +305,7 @@ private: */ class SoundMidiPC : public MidiDriver, public Sound { public: - SoundMidiPC(KyraEngine *vm, Audio::Mixer *mixer, MidiDriver *driver); + SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *driver); ~SoundMidiPC(); kType getMusicType() const { return isMT32() ? kMidiMT32 : kMidiGM; } @@ -378,7 +385,7 @@ private: class SoundTowns_EuphonyDriver; class SoundTowns : public MidiDriver, public Sound { public: - SoundTowns(KyraEngine *vm, Audio::Mixer *mixer); + SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer); ~SoundTowns(); kType getMusicType() const { return kTowns; } @@ -435,7 +442,7 @@ private: //class SoundTowns_v2_TwnDriver; class SoundTowns_v2 : public Sound { public: - SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer); + SoundTowns_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer); ~SoundTowns_v2(); kType getMusicType() const { return kTowns; } @@ -449,7 +456,7 @@ public: void haltTrack(); void beginFadeOut(); - bool voicePlay(const char *file, bool isSfx = false); + int32 voicePlay(const char *file, bool isSfx = false); void playSoundEffect(uint8) {} private: @@ -463,7 +470,7 @@ private: class MixedSoundDriver : public Sound { public: - MixedSoundDriver(KyraEngine *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx) : Sound(vm, mixer), _music(music), _sfx(sfx) {} + MixedSoundDriver(KyraEngine_v1 *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx) : Sound(vm, mixer), _music(music), _sfx(sfx) {} ~MixedSoundDriver() { delete _music; delete _sfx; } kType getMusicType() const { return _music->getMusicType(); } @@ -491,6 +498,8 @@ private: // Digital Audio class AUDStream; +class KyraAudioStream; +class KyraEngine_MR; /** * Digital audio output device. @@ -499,7 +508,7 @@ class AUDStream; */ class SoundDigital { public: - SoundDigital(KyraEngine *vm, Audio::Mixer *mixer); + SoundDigital(KyraEngine_MR *vm, Audio::Mixer *mixer); ~SoundDigital(); bool init() { return true; } @@ -535,7 +544,7 @@ public: void stopSound(int channel); /** - * Stops playback of all sounds + * Stops playback of all sounds. */ void stopAllSounds(); @@ -548,7 +557,7 @@ public: */ void beginFadeOut(int channel, int ticks); private: - KyraEngine *_vm; + KyraEngine_MR *_vm; Audio::Mixer *_mixer; struct Sound { @@ -556,8 +565,20 @@ private: char filename[16]; uint8 priority; - AUDStream *stream; + KyraAudioStream *stream; } _sounds[4]; + + struct AudioCodecs { + const char *fileext; + Audio::AudioStream *(*streamFunc)( + Common::SeekableReadStream *stream, + bool disposeAfterUse, + uint32 startTime, + uint32 duration, + uint numLoops); + }; + + static const AudioCodecs _supportedCodecs[]; }; } // end of namespace Kyra diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp index fa5a978665..68a2f0be9c 100644 --- a/engines/kyra/sound_adlib.cpp +++ b/engines/kyra/sound_adlib.cpp @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * LPGL License + * LGPL License * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -507,7 +507,7 @@ int AdlibDriver::snd_deinitDriver(va_list &list) { int AdlibDriver::snd_setSoundData(va_list &list) { if (_soundData) { - delete [] _soundData; + delete[] _soundData; _soundData = 0; } _soundData = va_arg(list, uint8*); @@ -2210,7 +2210,7 @@ const int SoundAdlibPC::_kyra1SoundTriggers[] = { const int SoundAdlibPC::_kyra1NumSoundTriggers = ARRAYSIZE(SoundAdlibPC::_kyra1SoundTriggers); -SoundAdlibPC::SoundAdlibPC(KyraEngine *vm, Audio::Mixer *mixer) +SoundAdlibPC::SoundAdlibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _driver(0), _trackEntries(), _soundDataPtr(0) { memset(_trackEntries, 0, sizeof(_trackEntries)); _v2 = (_vm->gameFlags().gameID == GI_KYRA2); @@ -2232,7 +2232,7 @@ SoundAdlibPC::SoundAdlibPC(KyraEngine *vm, Audio::Mixer *mixer) SoundAdlibPC::~SoundAdlibPC() { delete _driver; - delete [] _soundDataPtr; + delete[] _soundDataPtr; } bool SoundAdlibPC::init() { @@ -2382,7 +2382,7 @@ void SoundAdlibPC::loadSoundFile(uint file) { memcpy(_soundDataPtr, p, soundDataSize*sizeof(uint8)); - delete [] file_data; + delete[] file_data; file_data = p = 0; file_size = 0; diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index f8c6fbdb04..20f3a7f9f9 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -25,11 +25,83 @@ #include "kyra/sound.h" #include "kyra/resource.h" +#include "kyra/kyra_mr.h" #include "sound/audiostream.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" +#include "sound/flac.h" + namespace Kyra { +class KyraAudioStream : public Audio::AudioStream { +public: + KyraAudioStream(Audio::AudioStream *impl) : _impl(impl), _rate(impl->getRate()), _fadeSamples(0), _fadeCount(0), _fading(0), _endOfData(false) {} + ~KyraAudioStream() { delete _impl; _impl = 0; } + + int readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return _impl->isStereo(); } + bool endOfData() const { return _impl->endOfData() | _endOfData; } + int getRate() const { return _rate; } + int32 getTotalPlayTime() const { return _impl->getTotalPlayTime(); } + + void setRate(int newRate) { _rate = newRate; } + void beginFadeOut(uint32 millis); +private: + Audio::AudioStream *_impl; + + int _rate; + + int32 _fadeSamples; + int32 _fadeCount; + int _fading; + + bool _endOfData; +}; + +void KyraAudioStream::beginFadeOut(uint32 millis) { + _fadeSamples = (millis * getRate()) / 1000; + if (_fading == 0) + _fadeCount = _fadeSamples; + _fading = -1; +} + +int KyraAudioStream::readBuffer(int16 *buffer, const int numSamples) { + int samplesRead = _impl->readBuffer(buffer, numSamples); + + if (_fading) { + int samplesProcessed = 0; + for (; samplesProcessed < samplesRead; ++samplesProcessed) { + // To help avoid overflows for long fade times, we divide both + // _fadeSamples and _fadeCount when calculating the new sample. + + int32 div = _fadeSamples / 256; + if (_fading) { + *buffer = (*buffer * (_fadeCount / 256)) / div; + ++buffer; + + _fadeCount += _fading; + + if (_fadeCount < 0) { + _fadeCount = 0; + _endOfData = true; + } else if (_fadeCount > _fadeSamples) { + _fadeCount = _fadeSamples; + _fading = 0; + } + } + } + + if (_endOfData) { + memset(buffer, 0, (samplesRead - samplesProcessed) * sizeof(int16)); + samplesRead = samplesProcessed; + } + } + + return samplesRead; +} + // Thanks to Torbjorn Andersson (eriktorbjorn) for his aud player on which // this code is based on @@ -46,9 +118,6 @@ public: bool endOfData() const { return _endOfData; } int getRate() const { return _rate; } - - void beginFadeIn(uint32 millis); - void beginFadeOut(uint32 millis); private: Common::SeekableReadStream *_stream; bool _loop; @@ -67,10 +136,6 @@ private: byte *_inBuffer; uint _inBufferSize; - int32 _fadeSamples; - int32 _fadeCount; - int _fading; - int readChunk(int16 *buffer, const int maxSamples); static const int8 WSTable2Bit[]; @@ -91,9 +156,6 @@ AUDStream::AUDStream(Common::SeekableReadStream *stream, bool loop) : _stream(st _totalSize = _stream->readUint32LE(); _loop = loop; - _fadeSamples = 0; - _fading = 0; - // TODO?: add checks int flags = _stream->readByte(); // flags int type = _stream->readByte(); // type @@ -107,25 +169,11 @@ AUDStream::AUDStream(Common::SeekableReadStream *stream, bool loop) : _stream(st } AUDStream::~AUDStream() { - delete [] _outBuffer; - delete [] _inBuffer; + delete[] _outBuffer; + delete[] _inBuffer; delete _stream; } -void AUDStream::beginFadeIn(uint32 millis) { - _fadeSamples = (millis * getRate()) / 1000; - if (_fading == 0) - _fadeCount = 0; - _fading = 1; -} - -void AUDStream::beginFadeOut(uint32 millis) { - _fadeSamples = (millis * getRate()) / 1000; - if (_fading == 0) - _fadeCount = _fadeSamples; - _fading = -1; -} - int AUDStream::readBuffer(int16 *buffer, const int numSamples) { int samplesRead = 0, samplesLeft = numSamples; @@ -174,7 +222,7 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { if (size == outSize) { if (outSize > _outBufferSize) { _outBufferSize = outSize; - delete [] _outBuffer; + delete[] _outBuffer; _outBuffer = new uint8[_outBufferSize]; assert(_outBuffer); } @@ -187,14 +235,14 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { if (outSize > _outBufferSize) { _outBufferSize = outSize; - delete [] _outBuffer; + delete[] _outBuffer; _outBuffer = new uint8[_outBufferSize]; assert(_outBuffer); } if (size > _inBufferSize) { _inBufferSize = size; - delete [] _inBuffer; + delete[] _inBuffer; _inBuffer = new uint8[_inBufferSize]; assert(_inBuffer); } @@ -286,40 +334,19 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { samplesProcessed += samples; _bytesLeft -= samples; - // To help avoid overflows for long fade times, we divide both - // _fadeSamples and _fadeCount when calculating the new sample. - - int32 div = _fadeSamples / 256; - while (samples--) { int16 sample = (_outBuffer[_outBufferOffset++] << 8) ^ 0x8000; - if (_fading) { - sample = (sample * (_fadeCount / 256)) / div; - _fadeCount += _fading; - - if (_fadeCount < 0) { - _fadeCount = 0; - _endOfData = true; - } else if (_fadeCount > _fadeSamples) { - _fadeCount = _fadeSamples; - _fading = 0; - } - } - *buffer++ = sample; } } - if (_fading < 0 && _fadeCount == 0) - _fading = 0; - return samplesProcessed; } #pragma mark - -SoundDigital::SoundDigital(KyraEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _sounds() { +SoundDigital::SoundDigital(KyraEngine_MR *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _sounds() { for (uint i = 0; i < ARRAYSIZE(_sounds); ++i) _sounds[i].stream = 0; } @@ -365,7 +392,19 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer:: } } - Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filename); + Common::SeekableReadStream *stream = 0; + int usedCodec = -1; + for (int i = 0; _supportedCodecs[i].fileext; ++i) { + Common::String file = filename; + file += _supportedCodecs[i].fileext; + + if (!_vm->resource()->exists(file.c_str())) + continue; + + stream = _vm->resource()->getFileStream(file); + usedCodec = i; + } + if (!stream) { warning("Couldn't find soundfile '%s'", filename); return -1; @@ -373,7 +412,13 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer:: strncpy(use->filename, filename, sizeof(use->filename)); use->priority = priority; - use->stream = new AUDStream(stream, loop); + Audio::AudioStream *audioStream = _supportedCodecs[usedCodec].streamFunc(stream, true, 0, 0, loop ? 0 : 1); + if (!audioStream) { + warning("Couldn't create audio stream for file '%s'", filename); + return -1; + } + use->stream = new KyraAudioStream(audioStream); + assert(use->stream); if (use->stream->endOfData()) { delete use->stream; use->stream = 0; @@ -384,6 +429,9 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer:: if (volume > 255) volume = 255; volume = (volume * Audio::Mixer::kMaxChannelVolume) / 255; + + if (type == Audio::Mixer::kSpeechSoundType && _vm->heliumMode()) + use->stream->setRate(32765); _mixer->playInputStream(type, &use->handle, use->stream, -1, volume); @@ -423,5 +471,30 @@ void SoundDigital::beginFadeOut(int channel, int ticks) { _sounds[channel].stream->beginFadeOut(ticks * _vm->tickLength()); } +// static res + +namespace { + +Audio::AudioStream *makeAUDStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 startTime, uint32 duration, uint numLoops) { + return new AUDStream(stream, numLoops == 0 ? true : false); +} + +} // end of anonymous namespace + +const SoundDigital::AudioCodecs SoundDigital::_supportedCodecs[] = { +#ifdef USE_FLAC + { ".FLA", Audio::makeFlacStream }, +#endif // USE_FLAC +#ifdef USE_VORBIS + { ".OGG", Audio::makeVorbisStream }, +#endif // USE_VORBIS +#ifdef USE_MAD + { ".MP3", Audio::makeMP3Stream }, +#endif // USE_MAD + { ".AUD", makeAUDStream }, + { 0, 0 } +}; + + } // end of namespace Kyra diff --git a/engines/kyra/sound_v1.cpp b/engines/kyra/sound_lok.cpp index 8293eb7508..8a1d16a6b1 100644 --- a/engines/kyra/sound_v1.cpp +++ b/engines/kyra/sound_lok.cpp @@ -24,22 +24,22 @@ */ #include "kyra/sound.h" -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" namespace Kyra { -void KyraEngine_v1::snd_playSoundEffect(int track, int volume) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playSoundEffect(%d, %d)", track, volume); +void KyraEngine_LoK::snd_playSoundEffect(int track, int volume) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_LoK::snd_playSoundEffect(%d, %d)", track, volume); if ((_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) && track == 49) { snd_playWanderScoreViaMap(56, 1); return; } - KyraEngine::snd_playSoundEffect(track); + KyraEngine_v1::snd_playSoundEffect(track); } -void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playWanderScoreViaMap(%d, %d)", command, restart); +void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_LoK::snd_playWanderScoreViaMap(%d, %d)", command, restart); if (restart) _lastMusicCommand = -1; @@ -57,21 +57,21 @@ void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) { _sound->haltTrack(); } } else { - KyraEngine::snd_playWanderScoreViaMap(command, restart); + KyraEngine_v1::snd_playWanderScoreViaMap(command, restart); } } -void KyraEngine_v1::snd_playVoiceFile(int id) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playVoiceFile(%d)", id); +void KyraEngine_LoK::snd_playVoiceFile(int id) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_LoK::snd_playVoiceFile(%d)", id); char vocFile[9]; assert(id >= 0 && id < 9999); sprintf(vocFile, "%03d", id); _speechFile = vocFile; - _sound->voicePlay(vocFile); + _speechPlayTime = _sound->voicePlay(vocFile); } -void KyraEngine_v1::snd_voiceWaitForFinish(bool ingame) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_voiceWaitForFinish(%d)", ingame); +void KyraEngine_LoK::snd_voiceWaitForFinish(bool ingame) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_LoK::snd_voiceWaitForFinish(%d)", ingame); while (_sound->voiceIsPlaying() && !_skipFlag) { if (ingame) delay(10, true); @@ -80,4 +80,11 @@ void KyraEngine_v1::snd_voiceWaitForFinish(bool ingame) { } } +uint32 KyraEngine_LoK::snd_getVoicePlayTime() { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_LoK::snd_getVoicePlayTime()"); + if (!snd_voiceIsPlaying()) + return 0; + return (_speechPlayTime != -1 ? _speechPlayTime : 0); +} + } // end of namespace Kyra diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 9ac865c157..4265533507 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -599,18 +599,18 @@ SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() { MidiDriver_YM2612::removeLookupTables(); if (_fmInstruments) { - delete [] _fmInstruments; + delete[] _fmInstruments; _fmInstruments = 0; } if (_waveInstruments) { - delete [] _waveInstruments; + delete[] _waveInstruments; _waveInstruments = 0; } for (int i = 0; i < 10; i++) { if (_waveSounds[i]) { - delete [] _waveSounds[i]; + delete[] _waveSounds[i]; _waveSounds[i] = 0; } } @@ -709,14 +709,14 @@ void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) { void SoundTowns_EuphonyDriver::loadFmInstruments(const byte *instr) { if (_fmInstruments) - delete [] _fmInstruments; + delete[] _fmInstruments; _fmInstruments = new uint8[0x1800]; memcpy(_fmInstruments, instr, 0x1800); } void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) { if (_waveInstruments) - delete [] _waveInstruments; + delete[] _waveInstruments; _waveInstruments = new uint8[0x1000]; memcpy(_waveInstruments, instr, 0x1000); @@ -724,7 +724,7 @@ void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) { for (uint8 i = 0; i < 10; i++) { if (_waveSounds[i]) - delete [] _waveSounds[i]; + delete[] _waveSounds[i]; uint32 numsamples = READ_LE_UINT32(pos + 0x0C); _waveSounds[i] = new int8[numsamples + 0x20]; memcpy(_waveSounds[i], pos, 0x20); @@ -1010,7 +1010,7 @@ SoundTowns_EuphonyTrackQueue * SoundTowns_EuphonyTrackQueue::reset() { void SoundTowns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) { if (_trackData) - delete [] _trackData; + delete[] _trackData; _trackData = new uint8[0xC58A]; memset(_trackData, 0, 0xC58A); Screen::decodeFrame4(trackdata, _trackData, size); @@ -1051,13 +1051,13 @@ void SoundTowns_EuphonyTrackQueue::release() { _used = _fchan = _wchan = 0; if (_trackData) { - delete [] _trackData; + delete[] _trackData; _trackData = 0; } while (i) { if (i->_trackData) { - delete [] i->_trackData; + delete[] i->_trackData; i->_trackData = 0; } i = i->_next; @@ -1084,7 +1084,7 @@ void SoundTowns_EuphonyTrackQueue::initDriver() { _driver->send(0x79B0); } -SoundTowns::SoundTowns(KyraEngine *vm, Audio::Mixer *mixer) +SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _sfxBTTable(0), _parser(0) { @@ -1097,7 +1097,7 @@ SoundTowns::SoundTowns(KyraEngine *vm, Audio::Mixer *mixer) SoundTowns::~SoundTowns() { AudioCD.stop(); haltTrack(); - delete [] _sfxFileData; + delete[] _sfxFileData; Common::StackLock lock(_mutex); _driver->setTimerCallback(0, 0); @@ -1109,8 +1109,8 @@ SoundTowns::~SoundTowns() { bool SoundTowns::init() { _vm->checkCD(); int unused = 0; - _sfxWDTable = _vm->staticres()->loadRawData(kKyra1TownsSFXwdTable, unused); - _sfxBTTable = _vm->staticres()->loadRawData(kKyra1TownsSFXbtTable, unused); + _sfxWDTable = _vm->staticres()->loadRawData(k1TownsSFXwdTable, unused); + _sfxBTTable = _vm->staticres()->loadRawData(k1TownsSFXbtTable, unused); return loadInstruments(); } @@ -1164,7 +1164,7 @@ void SoundTowns::loadSoundFile(uint file) { if (_sfxFileIndex == file) return; _sfxFileIndex = file; - delete [] _sfxFileData; + delete[] _sfxFileData; _sfxFileData = _vm->resource()->fileData(fileListEntry(file), 0); } @@ -1293,7 +1293,7 @@ bool SoundTowns::loadInstruments() { _driver->queue()->loadDataToCurrentPosition(twm + 0x0CA0, 0xC58A); _driver->loadWaveInstruments(_driver->queue()->trackData() + 8); - delete [] twm; + delete[] twm; _driver->queue()->release(); return true; @@ -1301,6 +1301,7 @@ bool SoundTowns::loadInstruments() { void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); + Common::StackLock lock(_mutex); if (!_parser) { _parser = new MidiParser_EuD(_driver->queue()); @@ -1311,7 +1312,7 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { _parser->property(MidiParser::mpAutoLoop, loop); _parser->loadMusic(twm + 0x4b70 + offset, 0xC58A); - delete [] twm; + delete[] twm; } void SoundTowns::onTimer(void * data) { @@ -1357,7 +1358,7 @@ float SoundTowns::semitoneAndSampleRate_to_sampleStep(int8 semiTone, int8 semiTo // KYRA 2 -SoundTowns_v2::SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer) +SoundTowns_v2::SoundTowns_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), /*_driver(0),*/ _twnTrackData(0) { } @@ -1366,7 +1367,7 @@ SoundTowns_v2::~SoundTowns_v2() { /*if (_driver) delete _driver;*/ if (_twnTrackData) - delete [] _twnTrackData; + delete[] _twnTrackData; } bool SoundTowns_v2::init() { @@ -1416,7 +1417,7 @@ void SoundTowns_v2::playTrack(uint8 track) { char musicfile[13]; sprintf(musicfile, fileListEntry(0), track); if (_twnTrackData) - delete [] _twnTrackData; + delete[] _twnTrackData; _twnTrackData = _vm->resource()->fileData(musicfile, 0); //_driver->loadData(_twnTrackData); } @@ -1431,7 +1432,7 @@ void SoundTowns_v2::haltTrack() { //_driver->reset(); } -bool SoundTowns_v2::voicePlay(const char *file, bool) { +int32 SoundTowns_v2::voicePlay(const char *file, bool) { static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; int h = 0; @@ -1439,10 +1440,13 @@ bool SoundTowns_v2::voicePlay(const char *file, bool) { while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return false; + return 0; } - uint8 * data = _vm->resource()->fileData(file, 0); + char filename [13]; + sprintf(filename, "%s.PCM", file); + + uint8 * data = _vm->resource()->fileData(filename, 0); uint8 * src = data; uint16 sfxRate = rates[READ_LE_UINT16(src)]; @@ -1492,8 +1496,8 @@ bool SoundTowns_v2::voicePlay(const char *file, bool) { _soundChannels[h].file = file; _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h].channelHandle, _currentSFX); - delete [] data; - return true; + delete[] data; + return 1; } void SoundTowns_v2::beginFadeOut() { diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp index b54192abae..34c2986f25 100644 --- a/engines/kyra/sprites.cpp +++ b/engines/kyra/sprites.cpp @@ -30,14 +30,14 @@ #include "common/system.h" #include "common/events.h" #include "kyra/screen.h" -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/sprites.h" #include "kyra/resource.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" namespace Kyra { -Sprites::Sprites(KyraEngine_v1 *vm, OSystem *system) { +Sprites::Sprites(KyraEngine_LoK *vm, OSystem *system) { _vm = vm; _res = vm->resource(); _screen = vm->screen(); @@ -52,11 +52,11 @@ Sprites::Sprites(KyraEngine_v1 *vm, OSystem *system) { } Sprites::~Sprites() { - delete [] _dat; + delete[] _dat; freeSceneShapes(); for (int i = 0; i < MAX_NUM_ANIMS; i++) { if (_anims[i].background) - delete [] _anims[i].background; + delete[] _anims[i].background; } } @@ -66,7 +66,7 @@ void Sprites::setupSceneAnims() { for (int i = 0; i < MAX_NUM_ANIMS; i++) { if (_anims[i].background) { - delete [] _anims[i].background; + delete[] _anims[i].background; _anims[i].background = 0; } @@ -140,7 +140,7 @@ void Sprites::updateSceneAnims() { uint16 sound; for (int i = 0; i < MAX_NUM_ANIMS; i++) { - if (_anims[i].script == 0 || !_anims[i].play || _anims[i].nextRun != 0 && _anims[i].nextRun > currTime) + if (_anims[i].script == 0 || !_anims[i].play || (_anims[i].nextRun != 0 && _anims[i].nextRun > currTime)) continue; data = _anims[i].curPos; @@ -515,7 +515,7 @@ void Sprites::loadDat(const char *filename, SceneExits &exits) { void Sprites::freeSceneShapes() { debugC(9, kDebugLevelSprites, "Sprites::freeSceneShapes()"); for (int i = 0; i < ARRAYSIZE(_sceneShapes); i++ ) { - delete [] _sceneShapes[i]; + delete[] _sceneShapes[i]; _sceneShapes[i] = 0; } } @@ -554,7 +554,7 @@ void Sprites::loadSceneShapes() { void Sprites::refreshSceneAnimObject(uint8 animNum, uint8 shapeNum, uint16 x, uint16 y, bool flipX, bool unkFlag) { debugC(9, kDebugLevelSprites, "Sprites::refreshSceneAnimObject(%i, %i, %i, %i, %i, %i", animNum, shapeNum, x, y, flipX, unkFlag); - Animator_v1::AnimObject &anim = _vm->animator()->sprites()[animNum]; + Animator_LoK::AnimObject &anim = _vm->animator()->sprites()[animNum]; anim.refreshFlag = 1; anim.bkgdChangeFlag = 1; diff --git a/engines/kyra/sprites.h b/engines/kyra/sprites.h index 3304458fda..212bfc7428 100644 --- a/engines/kyra/sprites.h +++ b/engines/kyra/sprites.h @@ -26,7 +26,7 @@ #ifndef KYRA_SPRITES_H #define KYRA_SPRITES_H -#include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" namespace Kyra { @@ -63,11 +63,11 @@ struct Anim { bool disable; }; -class KyraEngine_v1; +class KyraEngine_LoK; class Sprites { public: - Sprites(KyraEngine_v1 *vm, OSystem *system); + Sprites(KyraEngine_LoK *vm, OSystem *system); ~Sprites(); void updateSceneAnims(); @@ -86,7 +86,7 @@ public: protected: void freeSceneShapes(); - KyraEngine_v1 *_vm; + KyraEngine_LoK *_vm; Resource *_res; OSystem *_system; Screen *_screen; diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 16d7ca4d9b..abdf115c1e 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -26,24 +26,23 @@ #include "common/endian.h" #include "common/md5.h" -#include "kyra/kyra.h" #include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" +#include "kyra/kyra_v2.h" #include "kyra/kyra_hof.h" #include "kyra/kyra_mr.h" #include "kyra/screen.h" -#include "kyra/screen_v1.h" +#include "kyra/screen_lok.h" #include "kyra/screen_hof.h" #include "kyra/screen_mr.h" #include "kyra/resource.h" -#include "kyra/gui_v1.h" +#include "kyra/gui_lok.h" #include "kyra/gui_hof.h" #include "kyra/gui_mr.h" -#include "gui/message.h" - namespace Kyra { -#define RESFILE_VERSION 24 +#define RESFILE_VERSION 28 bool StaticResource::checkKyraDat() { Common::File kyraDat; @@ -143,8 +142,8 @@ bool StaticResource::init() { { kPaletteTable, proc(loadPaletteTable), proc(freePaletteTable) }, { k2SeqData, proc(loadHofSequenceData), proc(freeHofSequenceData) }, - { k2ShpAnimDataV1, proc(loadHofShapeAnimDataV1), proc(freeHofShapeAnimDataV1) }, - { k2ShpAnimDataV2, proc(loadHofShapeAnimDataV2), proc(freeHofShapeAnimDataV2) }, + { k2ShpAnimDataV1, proc(loadShapeAnimData_v1), proc(freeHofShapeAnimDataV1) }, + { k2ShpAnimDataV2, proc(loadShapeAnimData_v2), proc(freeHofShapeAnimDataV2) }, { 0, 0, 0 } }; @@ -154,85 +153,85 @@ bool StaticResource::init() { // Kyrandia 1 Filenames static const FilenameTable kyra1StaticRes[] = { // INTRO / OUTRO sequences - { kForestSeq, kRawData, "FOREST.SEQ" }, - { kKallakWritingSeq, kRawData, "KALLAK-WRITING.SEQ" }, - { kKyrandiaLogoSeq, kRawData, "KYRANDIA-LOGO.SEQ" }, - { kKallakMalcolmSeq, kRawData, "KALLAK-MALCOLM.SEQ" }, - { kMalcolmTreeSeq, kRawData, "MALCOLM-TREE.SEQ" }, - { kWestwoodLogoSeq, kRawData, "WESTWOOD-LOGO.SEQ" }, - { kDemo1Seq, kRawData, "DEMO1.SEQ" }, - { kDemo2Seq, kRawData, "DEMO2.SEQ" }, - { kDemo3Seq, kRawData, "DEMO3.SEQ" }, - { kDemo4Seq, kRawData, "DEMO4.SEQ" }, - { kOutroReunionSeq, kRawData, "REUNION.SEQ" }, + { k1ForestSeq, kRawData, "FOREST.SEQ" }, + { k1KallakWritingSeq, kRawData, "KALLAK-WRITING.SEQ" }, + { k1KyrandiaLogoSeq, kRawData, "KYRANDIA-LOGO.SEQ" }, + { k1KallakMalcolmSeq, kRawData, "KALLAK-MALCOLM.SEQ" }, + { k1MalcolmTreeSeq, kRawData, "MALCOLM-TREE.SEQ" }, + { k1WestwoodLogoSeq, kRawData, "WESTWOOD-LOGO.SEQ" }, + { k1Demo1Seq, kRawData, "DEMO1.SEQ" }, + { k1Demo2Seq, kRawData, "DEMO2.SEQ" }, + { k1Demo3Seq, kRawData, "DEMO3.SEQ" }, + { k1Demo4Seq, kRawData, "DEMO4.SEQ" }, + { k1OutroReunionSeq, kRawData, "REUNION.SEQ" }, // INTRO / OUTRO strings - { kIntroCPSStrings, kStringList, "INTRO-CPS.TXT" }, - { kIntroCOLStrings, kStringList, "INTRO-COL.TXT" }, - { kIntroWSAStrings, kStringList, "INTRO-WSA.TXT" }, - { kIntroStrings, kLanguageList, "INTRO-STRINGS." }, - { kOutroHomeString, kLanguageList, "HOME." }, + { k1IntroCPSStrings, kStringList, "INTRO-CPS.TXT" }, + { k1IntroCOLStrings, kStringList, "INTRO-COL.TXT" }, + { k1IntroWSAStrings, kStringList, "INTRO-WSA.TXT" }, + { k1IntroStrings, kLanguageList, "INTRO-STRINGS." }, + { k1OutroHomeString, kLanguageList, "HOME." }, // INGAME strings - { kItemNames, kLanguageList, "ITEMLIST." }, - { kTakenStrings, kLanguageList, "TAKEN." }, - { kPlacedStrings, kLanguageList, "PLACED." }, - { kDroppedStrings, kLanguageList, "DROPPED." }, - { kNoDropStrings, kLanguageList, "NODROP." }, - { kPutDownString, kLanguageList, "PUTDOWN." }, - { kWaitAmuletString, kLanguageList, "WAITAMUL." }, - { kBlackJewelString, kLanguageList, "BLACKJEWEL." }, - { kPoisonGoneString, kLanguageList, "POISONGONE." }, - { kHealingTipString, kLanguageList, "HEALINGTIP." }, - { kThePoisonStrings, kLanguageList, "THEPOISON." }, - { kFluteStrings, kLanguageList, "FLUTE." }, - { kWispJewelStrings, kLanguageList, "WISPJEWEL." }, - { kMagicJewelStrings, kLanguageList, "MAGICJEWEL." }, - { kFlaskFullString, kLanguageList, "FLASKFULL." }, - { kFullFlaskString, kLanguageList, "FULLFLASK." }, - { kVeryCleverString, kLanguageList, "VERYCLEVER." }, - { kNewGameString, kLanguageList, "NEWGAME." }, + { k1ItemNames, kLanguageList, "ITEMLIST." }, + { k1TakenStrings, kLanguageList, "TAKEN." }, + { k1PlacedStrings, kLanguageList, "PLACED." }, + { k1DroppedStrings, kLanguageList, "DROPPED." }, + { k1NoDropStrings, kLanguageList, "NODROP." }, + { k1PutDownString, kLanguageList, "PUTDOWN." }, + { k1WaitAmuletString, kLanguageList, "WAITAMUL." }, + { k1BlackJewelString, kLanguageList, "BLACKJEWEL." }, + { k1PoisonGoneString, kLanguageList, "POISONGONE." }, + { k1HealingTipString, kLanguageList, "HEALINGTIP." }, + { k1ThePoisonStrings, kLanguageList, "THEPOISON." }, + { k1FluteStrings, kLanguageList, "FLUTE." }, + { k1WispJewelStrings, kLanguageList, "WISPJEWEL." }, + { k1MagicJewelStrings, kLanguageList, "MAGICJEWEL." }, + { k1FlaskFullString, kLanguageList, "FLASKFULL." }, + { k1FullFlaskString, kLanguageList, "FULLFLASK." }, + { k1VeryCleverString, kLanguageList, "VERYCLEVER." }, + { k1NewGameString, kLanguageList, "NEWGAME." }, // GUI strings table - { kGUIStrings, kLanguageList, "GUISTRINGS." }, - { kConfigStrings, kLanguageList, "CONFIGSTRINGS." }, + { k1GUIStrings, kLanguageList, "GUISTRINGS." }, + { k1ConfigStrings, kLanguageList, "CONFIGSTRINGS." }, // ROOM table/filenames - { Kyra::kRoomList, StaticResource::kRoomList, "ROOM-TABLE.ROOM" }, - { kRoomFilenames, kStringList, "ROOM-FILENAMES.TXT" }, + { k1RoomList, kRoomList, "ROOM-TABLE.ROOM" }, + { k1RoomFilenames, kStringList, "ROOM-FILENAMES.TXT" }, // SHAPE tables - { kDefaultShapes, kShapeList, "SHAPES-DEFAULT.SHP" }, - { kHealing1Shapes, kShapeList, "HEALING.SHP" }, - { kHealing2Shapes, kShapeList, "HEALING2.SHP" }, - { kPoisonDeathShapes, kShapeList, "POISONDEATH.SHP" }, - { kFluteShapes, kShapeList, "FLUTE.SHP" }, - { kWinter1Shapes, kShapeList, "WINTER1.SHP" }, - { kWinter2Shapes, kShapeList, "WINTER2.SHP" }, - { kWinter3Shapes, kShapeList, "WINTER3.SHP" }, - { kDrinkShapes, kShapeList, "DRINK.SHP" }, - { kWispShapes, kShapeList, "WISP.SHP" }, - { kMagicAnimShapes, kShapeList, "MAGICANIM.SHP" }, - { kBranStoneShapes, kShapeList, "BRANSTONE.SHP" }, + { k1DefaultShapes, kShapeList, "SHAPES-DEFAULT.SHP" }, + { k1Healing1Shapes, kShapeList, "HEALING.SHP" }, + { k1Healing2Shapes, kShapeList, "HEALING2.SHP" }, + { k1PoisonDeathShapes, kShapeList, "POISONDEATH.SHP" }, + { k1FluteShapes, kShapeList, "FLUTE.SHP" }, + { k1Winter1Shapes, kShapeList, "WINTER1.SHP" }, + { k1Winter2Shapes, kShapeList, "WINTER2.SHP" }, + { k1Winter3Shapes, kShapeList, "WINTER3.SHP" }, + { k1DrinkShapes, kShapeList, "DRINK.SHP" }, + { k1WispShapes, kShapeList, "WISP.SHP" }, + { k1MagicAnimShapes, kShapeList, "MAGICANIM.SHP" }, + { k1BranStoneShapes, kShapeList, "BRANSTONE.SHP" }, // IMAGE filename table - { kCharacterImageFilenames, kStringList, "CHAR-IMAGE.TXT" }, + { k1CharacterImageFilenames, kStringList, "CHAR-IMAGE.TXT" }, // AMULET anim - { kAmuleteAnimSeq, kRawData, "AMULETEANIM.SEQ" }, + { k1AmuleteAnimSeq, kRawData, "AMULETEANIM.SEQ" }, // PALETTE table - { kPaletteList, kPaletteTable, "1 33 PALTABLE" }, + { k1PaletteList, kPaletteTable, "1 33 PALTABLE" }, // AUDIO files - { kAudioTracks, kStringList, "TRACKS.TXT" }, - { kAudioTracksIntro, kStringList, "TRACKSINT.TXT" }, + { k1AudioTracks, kStringList, "TRACKS.TXT" }, + { k1AudioTracksIntro, kStringList, "TRACKSINT.TXT" }, // FM-TOWNS specific - { kKyra1TownsSFXwdTable, kRawData, "SFXWDTABLE" }, - { kKyra1TownsSFXbtTable, kRawData, "SFXBTTABLE" }, - { kKyra1TownsCDATable, kRawData, "CDATABLE" }, - { kCreditsStrings, kRawData, "CREDITS" }, + { k1TownsSFXwdTable, kRawData, "SFXWDTABLE" }, + { k1TownsSFXbtTable, kRawData, "SFXBTTABLE" }, + { k1TownsCDATable, kRawData, "CDATABLE" }, + { k1CreditsStrings, kRawData, "CREDITS" }, { 0, 0, 0 } }; @@ -261,7 +260,20 @@ bool StaticResource::init() { { k2IngameTalkObjIndex, kRawData, "I_TALKOBJECTS.MAP" }, { k2IngameTimJpStrings, kStringList, "I_TIMJPSTR.TXT" }, { k2IngameShapeAnimData, k2ShpAnimDataV2, "I_INVANIM.SHP" }, - { k2IngameTlkDemoStrings, kLanguageList, "I_TLKDEMO.TXT." }, + { k2IngameTlkDemoStrings, kLanguageList, "I_TLKDEMO.TXT." }, + + { 0, 0, 0 } + }; + + static const FilenameTable kyra3StaticRes[] = { + { k3MainMenuStrings, kStringList, "MAINMENU.TXT" }, + { k3MusicFiles, kStringList, "SCORE.TRA" }, + { k3ScoreTable, kRawData, "SCORE.MAP" }, + { k3SfxFiles, kStringList, "SFXFILES.TRA" }, + { k3SfxMap, kRawData, "SFXINDEX.MAP" }, + { k3ItemAnimData, k2ShpAnimDataV2, "INVANIM.SHP" }, + { k3ItemMagicTable, kRawData, "ITEMMAGIC.MAP" }, + { k3ItemStringMap, kRawData, "ITEMSTRINGS.MAP" }, { 0, 0, 0 } }; @@ -273,23 +285,26 @@ bool StaticResource::init() { _builtIn = 0; _filenameTable = kyra2StaticRes; } else if (_vm->game() == GI_KYRA3) { - return true; + _builtIn = 0; + _filenameTable = kyra3StaticRes; } else { error("unknown game ID"); } + char errorBuffer[100]; int tempSize = 0; uint8 *temp = getFile("INDEX", tempSize); if (!temp) { - warning("No matching INDEX file found ('%s')", getFilename("INDEX")); - outputError(); + snprintf(errorBuffer, sizeof(errorBuffer), "is missing an '%s' entry", getFilename("INDEX")); + outputError(errorBuffer); return false; } if (tempSize != 3*4) { - delete [] temp; - warning("'%s' has illegal filesize %d", getFilename("INDEX"), tempSize); - outputError(); + delete[] temp; + + snprintf(errorBuffer, sizeof(errorBuffer), "has incorrect header size for entry '%s'", getFilename("INDEX")); + outputError(errorBuffer); return false; } @@ -297,32 +312,29 @@ bool StaticResource::init() { uint32 gameID = READ_BE_UINT32((temp+4)); uint32 featuresValue = READ_BE_UINT32((temp+8)); - delete [] temp; + delete[] temp; temp = 0; if (version != RESFILE_VERSION) { - warning("Invalid KYRA.DAT file version (%u, required %d)", version, RESFILE_VERSION); - outputError(); + snprintf(errorBuffer, sizeof(errorBuffer), "has invalid version %d required, you got %d", RESFILE_VERSION, version); + outputError(errorBuffer); return false; } if (gameID != _vm->game()) { - warning("Invalid game id (%u)", gameID); - outputError(); + outputError("does not include support for your game"); return false; } uint32 gameFeatures = createFeatures(_vm->gameFlags()); if ((featuresValue & GAME_FLAGS) != gameFeatures) { - warning("Your data file has a different game flags (0x%.08X has the data and your version has 0x%.08X)", (featuresValue & GAME_FLAGS), gameFeatures); - outputError(); + outputError("does not include support for your game version"); return false; } // load all tables for now if (!prefetchId(-1)) { - warning("Couldn't load all needed resources from 'KYRA.DAT'"); - outputError(); + outputError("is lacking entries for your game version"); return false; } return true; @@ -332,11 +344,10 @@ void StaticResource::deinit() { unloadId(-1); } -void StaticResource::outputError() { - Common::String errorMessage = "Your '" + StaticResource::staticDataFilename() + "' file is outdated, reget it from the ScummVM website"; - ::GUI::MessageDialog errorMsg(errorMessage); - errorMsg.runModal(); - error(errorMessage.c_str()); +void StaticResource::outputError(const Common::String &error) { + Common::String errorMessage = "Your '" + StaticResource::staticDataFilename() + "' file " + error + ", reget a correct version from the ScummVM website"; + _vm->GUIErrorMessage(errorMessage); + ::error(errorMessage.c_str()); } const char * const*StaticResource::loadStrings(int id, int &strings) { @@ -366,11 +377,11 @@ const HofSeqData *StaticResource::loadHofSequenceData(int id, int &entries) { return (const HofSeqData*)getData(id, k2SeqData, entries); } -const ItemAnimData_v1 *StaticResource::loadHofShapeAnimDataV1(int id, int &entries) { +const ItemAnimData_v1 *StaticResource::loadShapeAnimData_v1(int id, int &entries) { return (const ItemAnimData_v1*)getData(id, k2ShpAnimDataV1, entries); } -const ItemAnimData_v2 *StaticResource::loadHofShapeAnimDataV2(int id, int &entries) { +const ItemAnimData_v2 *StaticResource::loadShapeAnimData_v2(int id, int &entries) { return (const ItemAnimData_v2*)getData(id, k2ShpAnimDataV2, entries); } @@ -545,7 +556,7 @@ bool StaticResource::loadStringTable(const char *filename, void *&ptr, int &size curPos += strLen+1; } - delete [] filePtr; + delete[] filePtr; ptr = output; return true; @@ -579,7 +590,7 @@ bool StaticResource::loadShapeTable(const char *filename, void *&ptr, int &size) loadTo[i].yOffset = *src++; } - delete [] filePtr; + delete[] filePtr; ptr = loadTo; return true; @@ -609,7 +620,7 @@ bool StaticResource::loadRoomTable(const char *filename, void *&ptr, int &size) memset(loadTo[i].needInit, 0, sizeof(loadTo[i].needInit)); } - delete [] filePtr; + delete[] filePtr; ptr = loadTo; return true; @@ -642,7 +653,7 @@ bool StaticResource::loadPaletteTable(const char *filename, void *&ptr, int &siz snprintf(name, 64, "%s%d.PAL", file, i); table[(start != 0) ? (i-start) : i] = (char*)getFile(name, size); if (!table[(start != 0) ? (i-start) : i]) { - delete [] table; + delete[] table; return false; } } @@ -743,7 +754,7 @@ bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int & } } - delete [] filePtr; + delete[] filePtr; HofSeqData *loadTo = new HofSeqData; assert(loadTo); @@ -758,7 +769,7 @@ bool StaticResource::loadHofSequenceData(const char *filename, void *&ptr, int & return true; } -bool StaticResource::loadHofShapeAnimDataV1(const char *filename, void *&ptr, int &size) { +bool StaticResource::loadShapeAnimData_v1(const char *filename, void *&ptr, int &size) { int filesize; uint8 *filePtr = getFile(filename, filesize); uint8 *src = filePtr; @@ -783,13 +794,13 @@ bool StaticResource::loadHofShapeAnimDataV1(const char *filename, void *&ptr, in loadTo[i].frames = tmp_f; } - delete [] filePtr; + delete[] filePtr; ptr = loadTo; return true; } -bool StaticResource::loadHofShapeAnimDataV2(const char *filename, void *&ptr, int &size) { +bool StaticResource::loadShapeAnimData_v2(const char *filename, void *&ptr, int &size) { int filesize; uint8 *filePtr = getFile(filename, filesize); uint8 *src = filePtr; @@ -815,7 +826,7 @@ bool StaticResource::loadHofShapeAnimDataV2(const char *filename, void *&ptr, in loadTo[i].frames = tmp_f; } - delete [] filePtr; + delete[] filePtr; ptr = loadTo; return true; @@ -823,7 +834,7 @@ bool StaticResource::loadHofShapeAnimDataV2(const char *filename, void *&ptr, in void StaticResource::freeRawData(void *&ptr, int &size) { uint8 *data = (uint8*)ptr; - delete [] data; + delete[] data; ptr = 0; size = 0; } @@ -831,21 +842,22 @@ void StaticResource::freeRawData(void *&ptr, int &size) { void StaticResource::freeStringTable(void *&ptr, int &size) { char **data = (char**)ptr; while (size--) - delete [] data[size]; + delete[] data[size]; + delete[] data; ptr = 0; size = 0; } void StaticResource::freeShapeTable(void *&ptr, int &size) { Shape *data = (Shape*)ptr; - delete [] data; + delete[] data; ptr = 0; size = 0; } void StaticResource::freeRoomTable(void *&ptr, int &size) { Room *data = (Room*)ptr; - delete [] data; + delete[] data; ptr = 0; size = 0; } @@ -854,16 +866,16 @@ void StaticResource::freeHofSequenceData(void *&ptr, int &size) { HofSeqData *h = (HofSeqData*) ptr; for (int i = 0; i < h->numSeq; i++) { - delete [] h->seq[i].wsaFile; - delete [] h->seq[i].cpsFile; + delete[] h->seq[i].wsaFile; + delete[] h->seq[i].cpsFile; } - delete [] h->seq; + delete[] h->seq; for (int i = 0; i < h->numSeqn; i++) { - delete [] h->seqn[i].wsaFile; - delete [] h->seqn[i].wsaControl; + delete[] h->seqn[i].wsaFile; + delete[] h->seqn[i].wsaControl; } - delete [] h->seqn; + delete[] h->seqn; delete h; ptr = 0; @@ -873,8 +885,8 @@ void StaticResource::freeHofSequenceData(void *&ptr, int &size) { void StaticResource::freeHofShapeAnimDataV1(void *&ptr, int &size) { ItemAnimData_v1 *d= (ItemAnimData_v1*) ptr; for (int i = 0; i < size; i++) - delete [] d[i].frames; - delete [] d; + delete[] d[i].frames; + delete[] d; ptr = 0; size = 0; } @@ -882,8 +894,8 @@ void StaticResource::freeHofShapeAnimDataV1(void *&ptr, int &size) { void StaticResource::freeHofShapeAnimDataV2(void *&ptr, int &size) { ItemAnimData_v2 *d= (ItemAnimData_v2*) ptr; for (int i = 0; i < size; i++) - delete [] d[i].frames; - delete [] d; + delete[] d[i].frames; + delete[] d; ptr = 0; size = 0; } @@ -891,7 +903,7 @@ void StaticResource::freeHofShapeAnimDataV2(void *&ptr, int &size) { void StaticResource::freePaletteTable(void *&ptr, int &size) { uint8 **data = (uint8**)ptr; while (size--) - delete [] data[size]; + delete[] data[size]; ptr = 0; size = 0; } @@ -903,8 +915,10 @@ const char *StaticResource::getFilename(const char *name) { if (_vm->gameFlags().gameID == GI_KYRA2) filename += ".K2"; + else if (_vm->gameFlags().gameID == GI_KYRA3) + filename += ".K3"; - if (_vm->gameFlags().isTalkie) + if (_vm->gameFlags().isTalkie && _vm->gameFlags().gameID != GI_KYRA3) filename += ".CD"; else if (_vm->gameFlags().isDemo) filename += ".DEM"; @@ -925,76 +939,76 @@ uint8 *StaticResource::getFile(const char *name, int &size) { #pragma mark - -void KyraEngine_v1::initStaticResource() { +void KyraEngine_LoK::initStaticResource() { int temp = 0; - _seq_Forest = _staticres->loadRawData(kForestSeq, temp); - _seq_KallakWriting = _staticres->loadRawData(kKallakWritingSeq, temp); - _seq_KyrandiaLogo = _staticres->loadRawData(kKyrandiaLogoSeq, temp); - _seq_KallakMalcolm = _staticres->loadRawData(kKallakMalcolmSeq, temp); - _seq_MalcolmTree = _staticres->loadRawData(kMalcolmTreeSeq, temp); - _seq_WestwoodLogo = _staticres->loadRawData(kWestwoodLogoSeq, temp); - _seq_Demo1 = _staticres->loadRawData(kDemo1Seq, temp); - _seq_Demo2 = _staticres->loadRawData(kDemo2Seq, temp); - _seq_Demo3 = _staticres->loadRawData(kDemo3Seq, temp); - _seq_Demo4 = _staticres->loadRawData(kDemo4Seq, temp); - _seq_Reunion = _staticres->loadRawData(kOutroReunionSeq, temp); - - _seq_WSATable = _staticres->loadStrings(kIntroWSAStrings, _seq_WSATable_Size); - _seq_CPSTable = _staticres->loadStrings(kIntroCPSStrings, _seq_CPSTable_Size); - _seq_COLTable = _staticres->loadStrings(kIntroCOLStrings, _seq_COLTable_Size); - _seq_textsTable = _staticres->loadStrings(kIntroStrings, _seq_textsTable_Size); - - _itemList = _staticres->loadStrings(kItemNames, _itemList_Size); - _takenList = _staticres->loadStrings(kTakenStrings, _takenList_Size); - _placedList = _staticres->loadStrings(kPlacedStrings, _placedList_Size); - _droppedList = _staticres->loadStrings(kDroppedStrings, _droppedList_Size); - _noDropList = _staticres->loadStrings(kNoDropStrings, _noDropList_Size); - _putDownFirst = _staticres->loadStrings(kPutDownString, _putDownFirst_Size); - _waitForAmulet = _staticres->loadStrings(kWaitAmuletString, _waitForAmulet_Size); - _blackJewel = _staticres->loadStrings(kBlackJewelString, _blackJewel_Size); - _poisonGone = _staticres->loadStrings(kPoisonGoneString, _poisonGone_Size); - _healingTip = _staticres->loadStrings(kHealingTipString, _healingTip_Size); - _thePoison = _staticres->loadStrings(kThePoisonStrings, _thePoison_Size); - _fluteString = _staticres->loadStrings(kFluteStrings, _fluteString_Size); - _wispJewelStrings = _staticres->loadStrings(kWispJewelStrings, _wispJewelStrings_Size); - _magicJewelString = _staticres->loadStrings(kMagicJewelStrings, _magicJewelString_Size); - _flaskFull = _staticres->loadStrings(kFlaskFullString, _flaskFull_Size); - _fullFlask = _staticres->loadStrings(kFullFlaskString, _fullFlask_Size); - _veryClever = _staticres->loadStrings(kVeryCleverString, _veryClever_Size); - _homeString = _staticres->loadStrings(kOutroHomeString, _homeString_Size); - _newGameString = _staticres->loadStrings(kNewGameString, _newGameString_Size); - - _healingShapeTable = _staticres->loadShapeTable(kHealing1Shapes, _healingShapeTableSize); - _healingShape2Table = _staticres->loadShapeTable(kHealing2Shapes, _healingShape2TableSize); - _posionDeathShapeTable = _staticres->loadShapeTable(kPoisonDeathShapes, _posionDeathShapeTableSize); - _fluteAnimShapeTable = _staticres->loadShapeTable(kFluteShapes, _fluteAnimShapeTableSize); - _winterScrollTable = _staticres->loadShapeTable(kWinter1Shapes, _winterScrollTableSize); - _winterScroll1Table = _staticres->loadShapeTable(kWinter2Shapes, _winterScroll1TableSize); - _winterScroll2Table = _staticres->loadShapeTable(kWinter3Shapes, _winterScroll2TableSize); - _drinkAnimationTable = _staticres->loadShapeTable(kDrinkShapes, _drinkAnimationTableSize); - _brandonToWispTable = _staticres->loadShapeTable(kWispShapes, _brandonToWispTableSize); - _magicAnimationTable = _staticres->loadShapeTable(kMagicAnimShapes, _magicAnimationTableSize); - _brandonStoneTable = _staticres->loadShapeTable(kBranStoneShapes, _brandonStoneTableSize); - - _characterImageTable = _staticres->loadStrings(kCharacterImageFilenames, _characterImageTableSize); - - _roomFilenameTable = _staticres->loadStrings(kRoomFilenames, _roomFilenameTableSize); - - _amuleteAnim = _staticres->loadRawData(kAmuleteAnimSeq, temp); - - _specialPalettes = _staticres->loadPaletteTable(kPaletteList, temp); - - _guiStrings = _staticres->loadStrings(kGUIStrings, _guiStringsSize); - _configStrings = _staticres->loadStrings(kConfigStrings, _configStringsSize); - - _soundFiles = _staticres->loadStrings(kAudioTracks, _soundFilesSize); - _soundFilesIntro = _staticres->loadStrings(kAudioTracksIntro, _soundFilesIntroSize); - _cdaTrackTable = (const int32*) _staticres->loadRawData(kKyra1TownsCDATable, _cdaTrackTableSize); + _seq_Forest = _staticres->loadRawData(k1ForestSeq, temp); + _seq_KallakWriting = _staticres->loadRawData(k1KallakWritingSeq, temp); + _seq_KyrandiaLogo = _staticres->loadRawData(k1KyrandiaLogoSeq, temp); + _seq_KallakMalcolm = _staticres->loadRawData(k1KallakMalcolmSeq, temp); + _seq_MalcolmTree = _staticres->loadRawData(k1MalcolmTreeSeq, temp); + _seq_WestwoodLogo = _staticres->loadRawData(k1WestwoodLogoSeq, temp); + _seq_Demo1 = _staticres->loadRawData(k1Demo1Seq, temp); + _seq_Demo2 = _staticres->loadRawData(k1Demo2Seq, temp); + _seq_Demo3 = _staticres->loadRawData(k1Demo3Seq, temp); + _seq_Demo4 = _staticres->loadRawData(k1Demo4Seq, temp); + _seq_Reunion = _staticres->loadRawData(k1OutroReunionSeq, temp); + + _seq_WSATable = _staticres->loadStrings(k1IntroWSAStrings, _seq_WSATable_Size); + _seq_CPSTable = _staticres->loadStrings(k1IntroCPSStrings, _seq_CPSTable_Size); + _seq_COLTable = _staticres->loadStrings(k1IntroCOLStrings, _seq_COLTable_Size); + _seq_textsTable = _staticres->loadStrings(k1IntroStrings, _seq_textsTable_Size); + + _itemList = _staticres->loadStrings(k1ItemNames, _itemList_Size); + _takenList = _staticres->loadStrings(k1TakenStrings, _takenList_Size); + _placedList = _staticres->loadStrings(k1PlacedStrings, _placedList_Size); + _droppedList = _staticres->loadStrings(k1DroppedStrings, _droppedList_Size); + _noDropList = _staticres->loadStrings(k1NoDropStrings, _noDropList_Size); + _putDownFirst = _staticres->loadStrings(k1PutDownString, _putDownFirst_Size); + _waitForAmulet = _staticres->loadStrings(k1WaitAmuletString, _waitForAmulet_Size); + _blackJewel = _staticres->loadStrings(k1BlackJewelString, _blackJewel_Size); + _poisonGone = _staticres->loadStrings(k1PoisonGoneString, _poisonGone_Size); + _healingTip = _staticres->loadStrings(k1HealingTipString, _healingTip_Size); + _thePoison = _staticres->loadStrings(k1ThePoisonStrings, _thePoison_Size); + _fluteString = _staticres->loadStrings(k1FluteStrings, _fluteString_Size); + _wispJewelStrings = _staticres->loadStrings(k1WispJewelStrings, _wispJewelStrings_Size); + _magicJewelString = _staticres->loadStrings(k1MagicJewelStrings, _magicJewelString_Size); + _flaskFull = _staticres->loadStrings(k1FlaskFullString, _flaskFull_Size); + _fullFlask = _staticres->loadStrings(k1FullFlaskString, _fullFlask_Size); + _veryClever = _staticres->loadStrings(k1VeryCleverString, _veryClever_Size); + _homeString = _staticres->loadStrings(k1OutroHomeString, _homeString_Size); + _newGameString = _staticres->loadStrings(k1NewGameString, _newGameString_Size); + + _healingShapeTable = _staticres->loadShapeTable(k1Healing1Shapes, _healingShapeTableSize); + _healingShape2Table = _staticres->loadShapeTable(k1Healing2Shapes, _healingShape2TableSize); + _posionDeathShapeTable = _staticres->loadShapeTable(k1PoisonDeathShapes, _posionDeathShapeTableSize); + _fluteAnimShapeTable = _staticres->loadShapeTable(k1FluteShapes, _fluteAnimShapeTableSize); + _winterScrollTable = _staticres->loadShapeTable(k1Winter1Shapes, _winterScrollTableSize); + _winterScroll1Table = _staticres->loadShapeTable(k1Winter2Shapes, _winterScroll1TableSize); + _winterScroll2Table = _staticres->loadShapeTable(k1Winter3Shapes, _winterScroll2TableSize); + _drinkAnimationTable = _staticres->loadShapeTable(k1DrinkShapes, _drinkAnimationTableSize); + _brandonToWispTable = _staticres->loadShapeTable(k1WispShapes, _brandonToWispTableSize); + _magicAnimationTable = _staticres->loadShapeTable(k1MagicAnimShapes, _magicAnimationTableSize); + _brandonStoneTable = _staticres->loadShapeTable(k1BranStoneShapes, _brandonStoneTableSize); + + _characterImageTable = _staticres->loadStrings(k1CharacterImageFilenames, _characterImageTableSize); + + _roomFilenameTable = _staticres->loadStrings(k1RoomFilenames, _roomFilenameTableSize); + + _amuleteAnim = _staticres->loadRawData(k1AmuleteAnimSeq, temp); + + _specialPalettes = _staticres->loadPaletteTable(k1PaletteList, temp); + + _guiStrings = _staticres->loadStrings(k1GUIStrings, _guiStringsSize); + _configStrings = _staticres->loadStrings(k1ConfigStrings, _configStringsSize); + + _soundFiles = _staticres->loadStrings(k1AudioTracks, _soundFilesSize); + _soundFilesIntro = _staticres->loadStrings(k1AudioTracksIntro, _soundFilesIntroSize); + _cdaTrackTable = (const int32*) _staticres->loadRawData(k1TownsCDATable, _cdaTrackTableSize); // copied static res // room list - const Room *tempRoomList = _staticres->loadRoomTable(kRoomList, _roomTableSize); + const Room *tempRoomList = _staticres->loadRoomTable(k1RoomList, _roomTableSize); if (_roomTableSize > 0) { _roomTable = new Room[_roomTableSize]; @@ -1003,11 +1017,11 @@ void KyraEngine_v1::initStaticResource() { memcpy(_roomTable, tempRoomList, _roomTableSize*sizeof(Room)); tempRoomList = 0; - _staticres->unloadId(kRoomList); + _staticres->unloadId(k1RoomList); } // default shape table - const Shape *tempShapeTable = _staticres->loadShapeTable(kDefaultShapes, _defaultShapeTableSize); + const Shape *tempShapeTable = _staticres->loadShapeTable(k1DefaultShapes, _defaultShapeTableSize); if (_defaultShapeTableSize > 0) { _defaultShapeTable = new Shape[_defaultShapeTableSize]; @@ -1016,7 +1030,7 @@ void KyraEngine_v1::initStaticResource() { memcpy(_defaultShapeTable, tempShapeTable, _defaultShapeTableSize*sizeof(Shape)); tempShapeTable = 0; - _staticres->unloadId(kDefaultShapes); + _staticres->unloadId(k1DefaultShapes); } // audio data tables @@ -1034,7 +1048,7 @@ void KyraEngine_v1::initStaticResource() { _soundData = (_flags.platform == Common::kPlatformPC) ? soundData_PC : soundData_TOWNS; } -void KyraEngine_v1::loadMouseShapes() { +void KyraEngine_LoK::loadMouseShapes() { _screen->loadBitmap("MOUSE.CPS", 3, 3, 0); _screen->_curPage = 2; _shapes[0] = _screen->encodeShape(0, 0, 8, 10, 0); @@ -1050,7 +1064,7 @@ void KyraEngine_v1::loadMouseShapes() { _screen->setShapePages(5, 3); } -void KyraEngine_v1::loadCharacterShapes() { +void KyraEngine_LoK::loadCharacterShapes() { int curImage = 0xFF; int videoPage = _screen->_curPage; _screen->_curPage = 2; @@ -1071,7 +1085,7 @@ void KyraEngine_v1::loadCharacterShapes() { _screen->_curPage = videoPage; } -void KyraEngine_v1::loadSpecialEffectShapes() { +void KyraEngine_LoK::loadSpecialEffectShapes() { _screen->loadBitmap("EFFECTS.CPS", 3, 3, 0); _screen->_curPage = 2; @@ -1089,7 +1103,7 @@ void KyraEngine_v1::loadSpecialEffectShapes() { _shapes[currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1); } -void KyraEngine_v1::loadItems() { +void KyraEngine_LoK::loadItems() { int shape; _screen->loadBitmap("JEWELS3.CPS", 3, 3, 0); @@ -1143,7 +1157,7 @@ void KyraEngine_v1::loadItems() { delete[] fileData; } -void KyraEngine_v1::loadButtonShapes() { +void KyraEngine_LoK::loadButtonShapes() { _screen->loadBitmap("BUTTONS2.CPS", 3, 3, 0); _screen->_curPage = 2; _gui->_scrollUpButton.data0ShapePtr = _screen->encodeShape(0, 0, 24, 14, 1); @@ -1155,7 +1169,7 @@ void KyraEngine_v1::loadButtonShapes() { _screen->_curPage = 0; } -void KyraEngine_v1::loadMainScreen(int page) { +void KyraEngine_LoK::loadMainScreen(int page) { _screen->clearPage(page); if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) @@ -1186,43 +1200,37 @@ void KyraEngine_HoF::initStaticResource() { _ingamePakList = _staticres->loadStrings(k2IngamePakFiles, _ingamePakListSize); _sequenceStrings = _staticres->loadStrings(k2SeqplayStrings, _sequenceStringsSize); _ingameSoundList = _staticres->loadStrings(k2IngameSfxFiles, _ingameSoundListSize); - _ingameSoundIndex = (const uint16*) _staticres->loadRawData(k2IngameSfxIndex, _ingameSoundIndexSize); + _ingameSoundIndex = (const uint16 *)_staticres->loadRawData(k2IngameSfxIndex, _ingameSoundIndexSize); _musicFileListIntro = _staticres->loadStrings(k2SeqplayIntroTracks, _musicFileListIntroSize); _musicFileListIngame = _staticres->loadStrings(k2IngameTracks, _musicFileListIngameSize); _musicFileListFinale = _staticres->loadStrings(k2SeqplayFinaleTracks, _musicFileListFinaleSize); _cdaTrackTableIntro = _staticres->loadRawData(k2SeqplayIntroCDA, _cdaTrackTableIntroSize); _cdaTrackTableIngame = _staticres->loadRawData(k2IngameCDA, _cdaTrackTableIngameSize); _cdaTrackTableFinale = _staticres->loadRawData(k2SeqplayFinaleCDA, _cdaTrackTableFinaleSize); - _ingameTalkObjIndex = (const uint16*) _staticres->loadRawData(k2IngameTalkObjIndex, _ingameTalkObjIndexSize); + _ingameTalkObjIndex = (const uint16 *)_staticres->loadRawData(k2IngameTalkObjIndex, _ingameTalkObjIndexSize); _ingameTimJpStr = _staticres->loadStrings(k2IngameTimJpStrings, _ingameTimJpStrSize); - _itemAnimData = _staticres->loadHofShapeAnimDataV2(k2IngameShapeAnimData, _itemAnimDataSize); + _itemAnimData = _staticres->loadShapeAnimData_v2(k2IngameShapeAnimData, _itemAnimDataSize); - // replace sequence talkie files with localized versions and cut off .voc - // suffix from voc files so as to allow compression specific file extensions - const char* const* seqSoundList = _staticres->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); - const char* const* tlkfiles = _staticres->loadStrings(k2SeqplayTlkFiles, tmpSize); - char ** tmpSndLst = new char*[_sequenceSoundListSize]; + // replace sequence talkie files with localized versions + const char *const *seqSoundList = _staticres->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); + const char *const *tlkfiles = _staticres->loadStrings(k2SeqplayTlkFiles, tmpSize); + char **tmpSndLst = new char*[_sequenceSoundListSize]; for (int i = 0; i < _sequenceSoundListSize; i++) { - int len = strlen(seqSoundList[i]); + const int len = strlen(seqSoundList[i]); tmpSndLst[i] = new char[len + 1]; tmpSndLst[i][0] = 0; - if (_flags.platform == Common::kPlatformPC) - len -= 4; - - if (tlkfiles) { + if (tlkfiles && len > 1) { for (int ii = 0; ii < tmpSize; ii++) { - if (!scumm_stricmp(&seqSoundList[i][1], &tlkfiles[ii][1])) - strcpy(tmpSndLst[i], tlkfiles[ii]); + if (strlen(tlkfiles[ii]) > 1 && !scumm_stricmp(&seqSoundList[i][1], &tlkfiles[ii][1])) + strcpy(tmpSndLst[i], tlkfiles[ii]); } } if (tmpSndLst[i][0] == 0) strcpy(tmpSndLst[i], seqSoundList[i]); - - tmpSndLst[i][len] = 0; } tlkfiles = seqSoundList = 0; @@ -1269,7 +1277,7 @@ void KyraEngine_HoF::initStaticResource() { &KyraEngine_HoF::seq_introLibrary2, &KyraEngine_HoF::seq_introLibrary2, &KyraEngine_HoF::seq_introMarco, &KyraEngine_HoF::seq_introHand1a, &KyraEngine_HoF::seq_introHand1b, &KyraEngine_HoF::seq_introHand1c, - &KyraEngine_HoF::seq_introHand2, &KyraEngine_HoF::seq_introHand3, 0 + &KyraEngine_HoF::seq_introHand2, &KyraEngine_HoF::seq_introHand3, 0 }; static const SeqProc hofDemoSequenceCallbacks[] = { @@ -1289,7 +1297,19 @@ void KyraEngine_HoF::initStaticResource() { _callbackN = (_flags.isDemo && !_flags.isTalkie) ? hofDemoNestedSequenceCallbacks : hofNestedSequenceCallbacks; } -const ScreenDim Screen_v1::_screenDimTable[] = { +void KyraEngine_MR::initStaticResource() { + int tmp = 0; + _mainMenuStrings = _staticres->loadStrings(k3MainMenuStrings, _mainMenuStringsSize); + _soundList = _staticres->loadStrings(k3MusicFiles, _soundListSize); + _scoreTable = _staticres->loadRawData(k3ScoreTable, _scoreTableSize); + _sfxFileList = _staticres->loadStrings(k3SfxFiles, _sfxFileListSize); + _sfxFileMap = _staticres->loadRawData(k3SfxMap, _sfxFileMapSize); + _itemAnimData = _staticres->loadShapeAnimData_v2(k3ItemAnimData, tmp); + _itemMagicTable = _staticres->loadRawData(k3ItemMagicTable, tmp); + _itemStringMap = _staticres->loadRawData(k3ItemStringMap, _itemStringMapSize); +} + +const ScreenDim Screen_LoK::_screenDimTable[] = { { 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 }, { 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 }, { 0x01, 0x08, 0x26, 0x80, 0x0F, 0x0C, 0x00, 0x00 }, @@ -1303,7 +1323,7 @@ const ScreenDim Screen_v1::_screenDimTable[] = { { 0x03, 0x28, 0x22, 0x46, 0x0F, 0x0D, 0x00, 0x00 } }; -const int Screen_v1::_screenDimTableCount = ARRAYSIZE(Screen_v1::_screenDimTable); +const int Screen_LoK::_screenDimTableCount = ARRAYSIZE(Screen_LoK::_screenDimTable); const ScreenDim Screen_HoF::_screenDimTable[] = { { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, @@ -1331,31 +1351,31 @@ const ScreenDim Screen_MR::_screenDimTable[] = { const int Screen_MR::_screenDimTableCount = ARRAYSIZE(Screen_MR::_screenDimTable); -const int8 KyraEngine::_addXPosTable[] = { +const int8 KyraEngine_v1::_addXPosTable[] = { 4, 4, 0, -4, -4, -4, 0, 4 }; -const int8 KyraEngine::_addYPosTable[] = { +const int8 KyraEngine_v1::_addYPosTable[] = { 0, -2, -2, -2, 0, 2, 2, 2 }; -const int8 KyraEngine_v1::_charXPosTable[] = { +const int8 KyraEngine_v1::_charAddXPosTable[] = { 0, 4, 4, 4, 0, -4, -4, -4 }; -const int8 KyraEngine_v1::_charYPosTable[] = { +const int8 KyraEngine_v1::_charAddYPosTable[] = { -2, -2, 0, 2, 2, 2, 0, -2 }; -const uint16 KyraEngine_v1::_itemPosX[] = { +const uint16 KyraEngine_LoK::_itemPosX[] = { 95, 115, 135, 155, 175, 95, 115, 135, 155, 175 }; -const uint8 KyraEngine_v1::_itemPosY[] = { +const uint8 KyraEngine_LoK::_itemPosY[] = { 160, 160, 160, 160, 160, 181, 181, 181, 181, 181 }; -void GUI_v1::initStaticResource() { +void GUI_LoK::initStaticResource() { GUI_V1_BUTTON(_scrollUpButton, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0x18, 0x0f, 0); GUI_V1_BUTTON(_scrollDownButton, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0x18, 0x0f, 0); @@ -1366,13 +1386,13 @@ void GUI_v1::initStaticResource() { GUI_V1_BUTTON(_menuButtonData[4], 0x10, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); GUI_V1_BUTTON(_menuButtonData[5], 0x11, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); - delete [] _menu; + delete[] _menu; _menu = new Menu[6]; assert(_menu); - Button::Callback quitPlayingFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::quitPlaying); - Button::Callback loadGameMenuFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::loadGameMenu); - Button::Callback cancelSubMenuFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::cancelSubMenu); + Button::Callback quitPlayingFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::quitPlaying); + Button::Callback loadGameMenuFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::loadGameMenu); + Button::Callback cancelSubMenuFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::cancelSubMenu); GUI_V1_MENU(_menu[0], -1, -1, 0x100, 0x8B, 248, 249, 250, 0, 251, -1, 8, 0, 5, -1, -1, -1, -1); GUI_V1_MENU_ITEM(_menu[0].item[0], 1, 0, 0, 0, -1, -1, 0x1E, 0xDC, 0x0F, 252, 253, -1, 0, 248, 249, 250, -1, 0, 0, 0, 0, 0); @@ -1381,16 +1401,16 @@ void GUI_v1::initStaticResource() { GUI_V1_MENU_ITEM(_menu[0].item[3], 1, 0, 0, 0, -1, -1, 0x51, 0xDC, 0x0F, 252, 253, -1, 0, 248, 249, 250, -1, 0, 0, 0, 0, 0); GUI_V1_MENU_ITEM(_menu[0].item[4], 1, 0, 0, 0, -1, 0, 0x6E, 0xDC, 0x0F, 252, 253, -1, 255, 248, 249, 250, -1, 0, 0, 0, 0, 0); _menu[0].item[0].callback = loadGameMenuFunctor; - _menu[0].item[1].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::saveGameMenu); - _menu[0].item[2].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::gameControlsMenu); + _menu[0].item[1].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::saveGameMenu); + _menu[0].item[2].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::gameControlsMenu); _menu[0].item[3].callback = quitPlayingFunctor; - _menu[0].item[4].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::resumeGame); + _menu[0].item[4].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::resumeGame); GUI_V1_MENU(_menu[1], -1, -1, 0x140, 0x38, 248, 249, 250, 0, 254,-1, 8, 0, 2, -1, -1, -1, -1); GUI_V1_MENU_ITEM(_menu[1].item[0], 1, 0, 0, 0, 0x18, 0, 0x1E, 0x48, 0x0F, 252, 253, -1, 255, 248, 249, 250, -1, 0, 0, 0, 0, 0); GUI_V1_MENU_ITEM(_menu[1].item[1], 1, 0, 0, 0, 0xD8, 0, 0x1E, 0x48, 0x0F, 252, 253, -1, 255, 248, 249, 250, -1, 0, 0, 0, 0, 0); - _menu[1].item[0].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::quitConfirmYes); - _menu[1].item[1].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::quitConfirmNo); + _menu[1].item[0].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::quitConfirmYes); + _menu[1].item[1].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::quitConfirmNo); GUI_V1_MENU(_menu[2], -1, -1, 0x120, 0xA0, 248, 249, 250, 0, 251, -1, 8, 0, 6, 132, 22, 132, 124); GUI_V1_MENU_ITEM(_menu[2].item[0], 1, 0, 0, 0, -1, 255, 0x27, 0x100, 0x0F, 252, 253, 5, 0, 248, 249, 250, -1, 0, 0, 0, 0, 0); @@ -1404,7 +1424,7 @@ void GUI_v1::initStaticResource() { GUI_V1_MENU(_menu[3], -1, -1, 288, 67, 248, 249, 250, 0, 251, -1, 8, 0, 2, -1, -1, -1, -1); GUI_V1_MENU_ITEM(_menu[3].item[0], 1, 0, 0, 0, 24, 0, 44, 85, 15, 252, 253, -1, 255, 248, 249, 250, -1, 0, 0, 0, 0, 0); GUI_V1_MENU_ITEM(_menu[3].item[1], 1, 0, 0, 0, 179, 0, 44, 85, 15, 252, 253, -1, 255, 248, 249, 250, -1, 0, 0, 0, 0, 0); - _menu[3].item[0].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::savegameConfirm); + _menu[3].item[0].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::savegameConfirm); _menu[3].item[1].callback = cancelSubMenuFunctor; GUI_V1_MENU(_menu[4], -1, -1, 0xD0, 0x4C, 248, 249, 250, 0, 251, -1, 8, 0, 2, -1, -1, -1, -1); @@ -1420,16 +1440,16 @@ void GUI_v1::initStaticResource() { GUI_V1_MENU_ITEM(_menu[5].item[3], 1, 0, 0, 0, 0xA5, 0, 0x51, 0x80, 0x0F, 252, 253, 5, 0, 248, 249, 250, -1, 0, 0x10, 0x53, 0, 0); GUI_V1_MENU_ITEM(_menu[5].item[4], 1, 0, 0, 0, 0xA5, 0, 0x62, 0x80, 0x0F, 252, 253, 5, 0, 248, 249, 250, -1, 0, 0x10, 0x65, 0, 0); GUI_V1_MENU_ITEM(_menu[5].item[5], 1, 0, 0, 0, -1, 0, 0x7F, 0x6C, 0x0F, 252, 253, -1, 255, 248, 249, 250, -1, -0, 0, 0, 0, 0); - _menu[5].item[0].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsChangeMusic); - _menu[5].item[1].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsChangeSounds); - _menu[5].item[2].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsChangeWalk); - _menu[5].item[4].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsChangeText); - _menu[5].item[5].callback = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::controlsApply); + _menu[5].item[0].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeMusic); + _menu[5].item[1].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeSounds); + _menu[5].item[2].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeWalk); + _menu[5].item[4].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeText); + _menu[5].item[5].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsApply); } -void KyraEngine_v1::setupButtonData() { - delete [] _buttonData; - delete [] _buttonDataListPtr; +void KyraEngine_LoK::setupButtonData() { + delete[] _buttonData; + delete[] _buttonDataListPtr; _buttonData = new Button[15]; assert(_buttonData); @@ -1437,9 +1457,9 @@ void KyraEngine_v1::setupButtonData() { assert(_buttonDataListPtr); GUI_V1_BUTTON(_buttonData[1], 0x01, 1, 1, 1, 0x0487, 0, 0x009, 0xA4, 0x36, 0x1E, 0); - _buttonData[1].buttonCallback = BUTTON_FUNCTOR(GUI_v1, _gui, &GUI_v1::buttonMenuCallback); + _buttonData[1].buttonCallback = BUTTON_FUNCTOR(GUI_LoK, _gui, &GUI_LoK::buttonMenuCallback); - Button::Callback inventoryFunctor = BUTTON_FUNCTOR(KyraEngine_v1, this, &KyraEngine_v1::buttonInventoryCallback); + Button::Callback inventoryFunctor = BUTTON_FUNCTOR(KyraEngine_LoK, this, &KyraEngine_LoK::buttonInventoryCallback); for (int i = 2; i <= 10; ++i) _buttonData[i].buttonCallback = inventoryFunctor; _buttonData[0].buttonCallback = inventoryFunctor; @@ -1454,7 +1474,7 @@ void KyraEngine_v1::setupButtonData() { GUI_V1_BUTTON(_buttonData[9], 0x0A, 0, 0, 0, 0x0400, 0, 0x099, 0xB3, 0x13, 0x14, 0); GUI_V1_BUTTON(_buttonData[10], 0x0B, 0, 0, 0, 0x0400, 0, 0x0AD, 0xB3, 0x13, 0x14, 0); - Button::Callback amuletFunctor = BUTTON_FUNCTOR(KyraEngine_v1, this, &KyraEngine_v1::buttonAmuletCallback); + Button::Callback amuletFunctor = BUTTON_FUNCTOR(KyraEngine_LoK, this, &KyraEngine_LoK::buttonAmuletCallback); GUI_V1_BUTTON(_buttonData[11], 0x15, 1, 1, 1, 0x0487, 0, 0x0FD, 0x9C, 0x1A, 0x12, 0); GUI_V1_BUTTON(_buttonData[12], 0x16, 1, 1, 1, 0x0487, 0, 0x0E7, 0xAA, 0x1A, 0x12, 0); GUI_V1_BUTTON(_buttonData[13], 0x17, 1, 1, 1, 0x0487, 0, 0x0FD, 0xB5, 0x1A, 0x12, 0); @@ -1467,29 +1487,29 @@ void KyraEngine_v1::setupButtonData() { _buttonDataListPtr[14] = 0; } -const uint8 KyraEngine_v1::_magicMouseItemStartFrame[] = { +const uint8 KyraEngine_LoK::_magicMouseItemStartFrame[] = { 0xAD, 0xB7, 0xBE, 0x00 }; -const uint8 KyraEngine_v1::_magicMouseItemEndFrame[] = { +const uint8 KyraEngine_LoK::_magicMouseItemEndFrame[] = { 0xB1, 0xB9, 0xC2, 0x00 }; -const uint8 KyraEngine_v1::_magicMouseItemStartFrame2[] = { +const uint8 KyraEngine_LoK::_magicMouseItemStartFrame2[] = { 0xB2, 0xBA, 0xC3, 0x00 }; -const uint8 KyraEngine_v1::_magicMouseItemEndFrame2[] = { +const uint8 KyraEngine_LoK::_magicMouseItemEndFrame2[] = { 0xB6, 0xBD, 0xC8, 0x00 }; -const uint16 KyraEngine_v1::_amuletX[] = { 231, 275, 253, 253 }; -const uint16 KyraEngine_v1::_amuletY[] = { 170, 170, 159, 181 }; +const uint16 KyraEngine_LoK::_amuletX[] = { 231, 275, 253, 253 }; +const uint16 KyraEngine_LoK::_amuletY[] = { 170, 170, 159, 181 }; -const uint16 KyraEngine_v1::_amuletX2[] = { 0x000, 0x0FD, 0x0E7, 0x0FD, 0x113, 0x000 }; -const uint16 KyraEngine_v1::_amuletY2[] = { 0x000, 0x09F, 0x0AA, 0x0B5, 0x0AA, 0x000 }; +const uint16 KyraEngine_LoK::_amuletX2[] = { 0x000, 0x0FD, 0x0E7, 0x0FD, 0x113, 0x000 }; +const uint16 KyraEngine_LoK::_amuletY2[] = { 0x000, 0x09F, 0x0AA, 0x0B5, 0x0AA, 0x000 }; -const int8 KyraEngine_v1::_dosTrackMap[] = { +const int8 KyraEngine_LoK::_dosTrackMap[] = { -1, 0, -1, 1, 0, 3, 0, 2, 0, 4, 1, 2, 1, 3, 1, 4, 1, 92, 1, 6, 1, 7, 2, 2, @@ -1506,18 +1526,10 @@ const int8 KyraEngine_v1::_dosTrackMap[] = { 8, 4, 8, 5, 6, 11, 5, 11 }; -const int KyraEngine_v1::_dosTrackMapSize = ARRAYSIZE(KyraEngine_v1::_dosTrackMap); +const int KyraEngine_LoK::_dosTrackMapSize = ARRAYSIZE(KyraEngine_LoK::_dosTrackMap); // kyra engine v2 static data -const int8 KyraEngine_v2::_updateCharPosXTable[] = { - 0, 4, 4, 4, 0, -4, -4, -4 -}; - -const int8 KyraEngine_v2::_updateCharPosYTable[] = { - -2, -2, 0, 2, 2, 2, 0, -2 -}; - const int GUI_v2::_sliderBarsPosition[] = { 0x92, 0x1F, 0x92, 0x30, 0x92, 0x41, 0x92, 0x52 }; @@ -1530,16 +1542,16 @@ const char *KyraEngine_HoF::_languageExtension[] = { "ENG", "FRE", "GER",/*, - "ITA", Italian and Spanish was never included + "ITA", Italian and Spanish were never included "SPA"*/ - "JPN" + "JPN", }; const char *KyraEngine_HoF::_scriptLangExt[] = { "EMC", "FMC", "GMC",/*, - "IMC", Italian and Spanish was never included + "IMC", Italian and Spanish were never included "SMC"*/ "JMC" }; @@ -1611,7 +1623,7 @@ const int8 KyraEngine_HoF::_dosTrackMap[] = { const int KyraEngine_HoF::_dosTrackMapSize = ARRAYSIZE(KyraEngine_HoF::_dosTrackMap); void KyraEngine_HoF::initInventoryButtonList() { - delete [] _inventoryButtons; + delete[] _inventoryButtons; _inventoryButtons = new Button[15]; assert(_inventoryButtons); @@ -1655,19 +1667,15 @@ void GUI_HoF::initStaticData() { GUI_V2_BUTTON(_scrollUpButton, 0x17, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0x18, 0x0F, 0xC7, 0xCF, 0xC7, 0xCF, 0xC7, 0xCF, 0); GUI_V2_BUTTON(_scrollDownButton, 0x18, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0x18, 0x0F, 0xC7, 0xCF, 0xC7, 0xCF, 0xC7, 0xCF, 0); - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) GUI_V2_BUTTON(_sliderButtons[0][i], 0x18+i, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0x0A, 0x0E, 0xC7, 0xCF, 0xC7, 0xCF, 0xC7, 0xCF, 0); - } - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) GUI_V2_BUTTON(_sliderButtons[1][i], 0x1C+i, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0x0A, 0x0E, 0xC7, 0xCF, 0xC7, 0xCF, 0xC7, 0xCF, 0); - } - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) GUI_V2_BUTTON(_sliderButtons[2][i], 0x20+i, 0, 0, 0, 0, 0, 0x2200, 0, 0, 0, 0x6E, 0x0E, 0xC7, 0xCF, 0xC7, 0xCF, 0xC7, 0xCF, 0); - } - for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) { + for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) GUI_V2_BUTTON(_menuButtons[i], 0x10+i, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0, 0, 0xC7, 0xCF, 0xC7, 0xCF, 0xC7, 0xCF, 0); - } Button::Callback clickLoadSlotFunctor = BUTTON_FUNCTOR(GUI_HoF, this, &GUI_HoF::clickLoadSlot); Button::Callback clickSaveSlotFunctor = BUTTON_FUNCTOR(GUI_HoF, this, &GUI_HoF::clickSaveSlot); @@ -1932,74 +1940,11 @@ const uint8 KyraEngine_HoF::_rainbowRoomData[] = { // kyra 3 static res -const char *KyraEngine_MR::_mainMenuStrings[] = { - "Start a new game", - "Introduction", - "Load a game", - "Exit the game", - "Nouvelle Partie", - "Introduction", - "Charger une partie", - "Quitter le jeu", - "Neues Spiel starten", - "Intro", - "Spielstand laden", - "Spiel beenden", - 0 -}; - -const char *KyraEngine_MR::_soundList[] = { - "ARREST1.AUD", - "BATH1.AUD", - "OCEAN1.AUD", - "CLOWN1.AUD", - "DARM2.AUD", - "FALL1M.AUD", - "FALL2.AUD", - "FISH1.AUD", - "FISHWNDR.AUD", - "HERMAN1.AUD", - "JAIL1.AUD", - "JUNGLE1.AUD", - "KATHY1.AUD", - "NICESINE.AUD", - "PEGASUS1.AUD", - "PIRATE1.AUD", - "PIRATE2.AUD", - "PIRATE3.AUD", - "POP3.AUD", - "PORT1.AUD", - "QUEEN1.AUD", - "RUINS1.AUD", - "SNAKES1.AUD", - "SPRING1.AUD", - "STATUE1.AUD", - "STATUE2.AUD", - "TITLE1.AUD", - "UNDER1.AUD", - "WALKCHP1.AUD", - "YANK1.AUD", - "ZAN2.AUD", - "GROOVE2.AUD", - "GROOVE3.AUD", - "KING1.AUD", - "KING2.AUD", - "GROOVE1.AUD", - "JAIL2.AUD", - "SPIRIT1.AUD", - "SPRING1A.AUD", - "POP1.AUD", - "POP2.AUD", - "SQUIRL1.AUD" -}; - -const int KyraEngine_MR::_soundListSize = ARRAYSIZE(KyraEngine_MR::_soundList); - const char *KyraEngine_MR::_languageExtension[] = { "TRE", "TRF", "TRG"/*, - "TRI", Italian and Spanish was never included + "TRI", Italian and Spanish were never included "TRS"*/ }; @@ -2026,316 +1971,6 @@ const uint8 KyraEngine_MR::_characterFrameTable[] = { 0x36, 0x35, 0x35, 0x33, 0x32, 0x32, 0x34, 0x34 }; -const uint8 KyraEngine_MR::_sfxFileMap[] = { - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x99, 0x00, - 0x46, 0x00, 0xA9, 0x00, 0x33, 0x00, 0x65, 0x00, - 0x9B, 0x00, 0x17, 0x00, 0xBB, 0x00, 0x64, 0x00, - 0x55, 0x00, 0xD5, 0x00, 0x66, 0x00, 0xB9, 0x00, - 0x9A, 0x00, 0xFF, 0x00, 0xCC, 0x00, 0x67, 0x00, - 0x2E, 0x00, 0xA1, 0x00, 0xD0, 0x00, 0x63, 0x00, - 0x89, 0x00, 0xBE, 0x00, 0x80, 0x00, 0x1D, 0x00, - 0x02, 0x00, 0x28, 0x00, 0x91, 0x00, 0x29, 0x00, - 0xCE, 0x00, 0x8F, 0x00, 0x49, 0x00, 0x2B, 0x00, - 0x2D, 0x00, 0x2C, 0x00, 0x3E, 0x00, 0x22, 0x00, - 0x80, 0x00, 0x9C, 0x00, 0x2E, 0x00, 0x04, 0x00, - 0x47, 0x00, 0xA8, 0x00, 0x51, 0x00, 0x52, 0x00, - 0x80, 0x00, 0x48, 0x00, 0x38, 0x0A, 0x0C, 0x00, - 0xD8, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, - 0xD1, 0x00, 0x6A, 0x00, 0x8A, 0x00, 0xC0, 0x00, - 0xC1, 0x00, 0xC2, 0x00, 0x9F, 0x00, 0xA3, 0x00, - 0x90, 0x00, 0xB6, 0x00, 0x37, 0x00, 0x71, 0x00, - 0x13, 0x00, 0x50, 0x00, 0x5A, 0x00, 0x6E, 0x00, - 0x70, 0x00, 0x11, 0x00, 0x16, 0x00, 0x14, 0x00, - 0x43, 0x00, 0xCD, 0x00, 0xAA, 0x00, 0x15, 0x00, - 0x83, 0x00, 0x19, 0x00, 0xB3, 0x00, 0x6F, 0x00, - 0x26, 0x00, 0xC8, 0x00, 0xA7, 0x00, 0x98, 0x00, - 0x87, 0x00, 0xC7, 0x00, 0xA2, 0x00, 0xB0, 0x00, - 0x12, 0x00, 0xD7, 0x00, 0x56, 0x00, 0x45, 0x00, - 0x4B, 0x00, 0xAF, 0x00, 0x3B, 0x00, 0x6C, 0x00, - 0x8E, 0x00, 0x39, 0x00, 0x38, 0x00, 0x92, 0x00, - 0x4B, 0x00, 0xD0, 0x00, 0x4A, 0x00, 0x9D, 0x00, - 0x7F, 0x00, 0x6D, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x3D, 0x00, 0x72, 0x00, 0x40, 0x00, 0x66, 0x00, - 0x01, 0x00, 0xA5, 0x00, 0x00, 0x00, 0x3C, 0x00, - 0xAC, 0x00, 0x38, 0x00, 0x8B, 0x00, 0xDF, 0x00, - 0x0E, 0x00, 0x54, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x94, 0x00, 0xAB, 0x00, 0x76, 0x00, 0x58, 0x00, - 0x6B, 0x00, 0x27, 0x00, 0xFF, 0x00, 0x77, 0x00, - 0xA6, 0x00, 0x63, 0x00, 0x9E, 0x00, 0xDE, 0x00, - 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x3F, 0x00, - 0xCC, 0x00, 0xCC, 0x00, 0xCC, 0x00, 0x93, 0x00, - 0x9D, 0x00, 0x75, 0x00, 0x75, 0x00, 0x75, 0x00, - 0x75, 0x00, 0x3A, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0xFF, 0x00, 0xAE, 0x00, 0x8C, 0x00, 0x20, 0x00, - 0xFF, 0x00, 0x32, 0x00, 0x32, 0x00, 0xFF, 0x00, - 0x4D, 0x00, 0xD9, 0x00, 0x88, 0x00, 0x4D, 0x00, - 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0xA0, 0x00, - 0x4C, 0x00, 0x8C, 0x00, 0x4C, 0x00, 0x4C, 0x00, - 0x8C, 0x00, 0x8C, 0x00, 0x5C, 0x00, 0x5D, 0x00, - 0x60, 0x00, 0x5F, 0x00, 0xC5, 0x00, 0xBF, 0x00, - 0xFF, 0x00, 0x4F, 0x00, 0x16, 0x00, 0x59, 0x00, - 0xFF, 0x00, 0x24, 0x00, 0xA4, 0x00, 0xCF, 0x00, - 0xFF, 0x00, 0x47, 0x00, 0x95, 0x00, 0x96, 0x00, - 0x7B, 0x00, 0xBD, 0x00, 0xFF, 0x00, 0x34, 0x00, - 0x35, 0x00, 0x36, 0x00, 0xDE, 0x00, 0xFF, 0x00, - 0x4B, 0x00, 0xD6, 0x00, 0xFF, 0x00, 0x61, 0x00, - 0x62, 0x00, 0xFF, 0x00, 0x78, 0x00, 0xFF, 0x00, - 0x44, 0x00, 0xB4, 0x00, 0xB5, 0x00, 0x42, 0x00, - 0x27, 0x00, 0xA2, 0x00, 0x27, 0x00, 0x5D, 0x00, - 0x7A, 0x00, 0x89, 0x00, 0x1A, 0x00, 0x0E, 0x00, - 0x82, 0x00, 0xFF, 0x00, 0x79, 0x00, 0x2A, 0x00, - 0x81, 0x00, 0xFF, 0x00, 0x74, 0x00, 0x4E, 0x00, - 0xB1, 0x00, 0x1B, 0x00, 0x2F, 0x00, 0xBA, 0x00, - 0xBB, 0x00, 0xBC, 0x00, 0xDA, 0x00, 0xDB, 0x00, - 0x18, 0x00, 0x5E, 0x00, 0x0D, 0x0A, 0x88, 0x00, - 0x1E, 0x00, 0x1F, 0x00, 0x20, 0x00, 0x21, 0x00, - 0x69, 0x00, 0x1C, 0x00, 0x7C, 0x00, 0x30, 0x00, - 0xC3, 0x00, 0xC4, 0x00, 0xAD, 0x00, 0x25, 0x00, - 0x53, 0x00, 0xB7, 0x00, 0xB8, 0x00, 0xDC, 0x00, - 0x8D, 0x00, 0xCB, 0x00, 0xD4, 0x00, 0xB2, 0x00, - 0xDD, 0x00, 0x57, 0x00, 0x41, 0x00, 0x10, 0x00, - 0x4C, 0x00, 0xC9, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x7D, 0x00, 0x7E, 0x00, 0xCA, 0x00, 0x03, 0x00, - 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x23, 0x00, 0x97, 0x00, 0x73, 0x00 -}; - -const int KyraEngine_MR::_sfxFileMapSize = ARRAYSIZE(KyraEngine_MR::_sfxFileMap); - -const char *KyraEngine_MR::_sfxFileList[] = { - "ALARM1", - "ARMOIRE1", - "ARROW1", - "AUDLAFF1", - "AUDLAFF2", - "AUDLAFF3", - "AUDLAFF4", - "AUDLAFF5", - "AUDLAFF6", - "AUDLAFF7", - "AUDLAFF8", - "AUDLAFF9", - "BARK22A", - "BEAM1", - "BEDSQK1", - "BEDSQK2", - "BIGCLOK1", - "BIGDOR2", - "BIRD4", - "BIRD122", - "BIRD222", - "BIRD322", - "BLAST22D", - "BLINK1", - "BOATMIX1", - "BODYFAL1", - "BOTLBLOW", - "BOUNCE3", - "BOUNCE5", - "BOW2", - "BUBL1", - "BUBL2", - "BUBL3", - "BUBL4", - "BUTTON1", - "BUTTON2", - "CANNON1", - "CASHREG1", - "CATHY1", - "CHAIN1", - "CHATTER1", - "CHATTER2", - "CHEESE1", - "CHICHIC2", - "CHIPLAF1", - "CHIPROR1", - "CLANG1", - "CLDOOR1", - "CLEAT1", - "CLOTHES1", - "COIN2", - "COUNTER1", - "CREAK1", - "CREAK2", - "CREAK3", - "CRIKT22A", - "CRMAD1", - "CRNORM1", - "CRUMBLE1", - "CRUNCH1", - "CRYSTAL1", - "DFLY1", - "DIAL1", - "DIGDIRT1", - "DIZZY1", - "DODO1", - "DOORBELL", - "DOORCL1", - "DOOROP1", - "DRIP1", - "DROPITM1", - "EAT22A", - "EATNUT1", - "ELEC1", - "EXPLODE2", - "FALL1", - "FALLM2", - "FALLM3", - "FESTRE1", - "FISHLAF2", - "FLAG22A", - "FLAG22B", - "FLAG22C", - "FLPOOF1", - "FOLDER1", - "FROG1", - "FROGJMP1", - "FSHBUBL1", - "FUNNEL1", - "FUSE1", - "GATE22A", - "GEM1", - "GEMFIRE1", - "GEMLIT1", - "GEMPUT1", - "GEMRAIN1", - "GEMWND1", - "GIRLLAF1", - "GIRLLAF2", - "GLASBRK1", - "GLOWY1", - "GOODK33", - "GROWTWIG", - "GUNTHER3", - "H2ODROP2", - "H2OFALL1", - "HAMMER1", - "HAYFALL2", - "HERMMAG1", - "HIPRES1", - "HITHED22", - "HOWL1", - "HUM1", - "HYPNO1", - "HYPNO2", - "IMPACT1", - "JOHAN1", - "JUNGAMB2", - "KISS1", - "KISS2", - "KNIFE", - "KNIFHIT1", - "KNIFSTAB", - "KNOCK", - "LAND1", - "LEVIBAB1", - "LEVIMAN1", - "LID", - "MACHMIX1", - "MALCFALL", - "MALCYAWN", - "MJUMP1", - "MOO1", - "MOO2", - "MOO3", - "MORPH1", - "MORPH2", - "MORPH3", - "MORPH4", - "MOTHS1", - "MSPLASH1", - "MTLSLAM1", - "MUDBATH1", - "NAIL1", - "NEIGH1", - "NETCATCH", - "NETMAL1", - "NETRIP1", - "OPDOOR1", - "OWL1", - "OWL2", - "PEDAL3", - "PEGWING1", - "PICKUP1", - "PLUCK3", - "POLGULP1", - "POOF1", - "PORTAL1", - "POURH2O1", - "PRIMOR1", - "PUMP1", - "PUNCTRE1", - "RATTLE1", - "REV2", - "RING", - "ROAR3", - "ROWBOAT1", - "RUCKUS1", - "RUMBLE1", - "SCOLD1", - "SCRATCH1", - "SHOVEL1", - "SHOWER2", - "SLOTPUL1", - "SNAKKILL", - "SNAP1", - "SNIFF1", - "SNIFF2", - "SNIFFM1", - "SNIP22B", - "SNORIN1", - "SNOROUT1", - "SNORT1", - "SPITBAL1", - "SPITBAL2", - "SPLASH1", - "SQUEAK1", - "SQUEAK2", - "SQUEAK3", - "STATUE", - "STAMPED1", - "STARS1", - "STONE1", - "STONE2", - "STONE3", - "STRETCH1", - "STRETCH2", - "SUNRISE1", - "SWALLOW1", - "SWALLOW2", - "SWAV22B", - "TELBEL1", - "TELBEL2", - "TENNIS1", - "THROW1", - "THUMP1", - "TOILET1", - "TRAPDOR1", - "TRICKLE", - "TROLGRNT", - "TROLYEL1", - "TROLYEL2", - "TUBEDOR1", - "TWIGSNAP", - "UMBRLA1", - "UNLOK22A", - "VACUUM", - "WAVELT1", - "WHIP1", - "WHIP2", - "WOODHIT1", - "YAWN1", - "ZING", - "ZIPPER1" -}; - -const int KyraEngine_MR::_sfxFileListSize = ARRAYSIZE(KyraEngine_MR::_sfxFileList); - const uint8 KyraEngine_MR::_badConscienceFrameTable[] = { 0x13, 0x13, 0x13, 0x18, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x13, 0x13, 0x13, 0x13, @@ -2376,28 +2011,6 @@ const uint8 KyraEngine_MR::_trashItemList[] = { 0x39, 0x40, 0x3E, 0x3D, 0x3C, 0x3F, 0xFF }; -const uint8 KyraEngine_MR::_itemMagicTable[] = { - 0x06, 0x05, 0x07, 0xFE, 0x05, 0x06, 0x07, 0xFE, - 0x03, 0x00, 0x22, 0xFE, 0x00, 0x03, 0x22, 0xFE, - 0x10, 0x00, 0x20, 0x0F, 0x00, 0x10, 0x0F, 0x20, - 0x10, 0x22, 0x21, 0x0F, 0x22, 0x10, 0x0F, 0x21, - 0xFF, 0xFF, 0xFF, 0xFF -}; - -const uint8 KyraEngine_MR::_itemStringMap[] = { - 1, 0, 2, 0, 2, 2, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 3, 1, - 2, 0, 2, 2, 0, 0, 0, 0, - 0, 0, 1, 2, 0, 2, 0, 2, - 0, 0, 2, 0, 0, 0, 0, 1, - 1, 0, 2, 2, 0, 0, 2, 0, - 0, 2, 0, 2, 2, 0, 0, 2, - 0, 0, 0, 0, 2, 0, 0, 2 -}; - -const uint KyraEngine_MR::_itemStringMapSize = ARRAYSIZE(KyraEngine_MR::_itemStringMap); - const uint8 KyraEngine_MR::_itemStringPickUp[] = { 0x4, 0x7, 0x0, 0xA }; @@ -2410,36 +2023,6 @@ const uint8 KyraEngine_MR::_itemStringInv[] = { 0x6, 0x9, 0x2, 0xC }; -const int8 KyraEngine_MR::_scoreTable[] = { - 10, 8, 5, 9, 10, 10, 7, 8, - 9, 9, 8, 8, 7, 8, 5, 9, - 6, 10, 7, 8, 5, 9, 6, 6, - 7, 8, 5, 9, 6, 8, 7, 8, - 5, 9, 6, 10, 7, 8, 5, 5, - 5, 7, 5, 7, 10, 5, 10, 5, - 5, 8, 6, 8, 7, 5, 5, 8, - 6, 9, 5, 7, 6, 5, 5, 7, - 7, 7, 6, 5, 8, 6, 10, 5, - 7, 5, 10, 5, 5, 5, 5, 7, - 5, 8, 9, 7, 7, 6, 10, 6, - 5, 10, 8, 5, 8, 6, 10, 5, - 5, 8, 8, 5, 7, 7, 7, 6, - 8, 9, 8, 8, 6, 5, 7, 6, - 5, 8, 15, 7, 9, 6, 6, 8, - 5, 8, 15, 15, 5, 15, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -const int KyraEngine_MR::_scoreTableSize = ARRAYSIZE(KyraEngine_MR::_scoreTable); - void KyraEngine_MR::initMainButtonList(bool disable) { if (!_mainButtonListInitialized) { _mainButtonData = new Button[14]; @@ -2483,19 +2066,15 @@ void GUI_MR::initStaticData() { GUI_V2_BUTTON(_scrollUpButton, 22, 0, 0, 4, 4, 4, 0x4487, 0, 0, 0, 0x18, 0x0F, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); GUI_V2_BUTTON(_scrollDownButton, 23, 0, 0, 4, 4, 4, 0x4487, 0, 0, 0, 0x18, 0x0F, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) GUI_V2_BUTTON(_sliderButtons[0][i], 0x18+i, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0x0A, 0x0E, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); - } - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) GUI_V2_BUTTON(_sliderButtons[1][i], 0x1C+i, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0x0A, 0x0E, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); - } - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) GUI_V2_BUTTON(_sliderButtons[2][i], 0x20+i, 0, 0, 0, 0, 0, 0x2200, 0, 0, 0, 0x6E, 0x0E, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); - } - for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) { + for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) GUI_V2_BUTTON(_menuButtons[i], 0x0F+i, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 0, 0, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); - } Button::Callback clickLoadSlotFunctor = BUTTON_FUNCTOR(GUI_MR, this, &GUI_MR::clickLoadSlot); Button::Callback clickSaveSlotFunctor = BUTTON_FUNCTOR(GUI_MR, this, &GUI_MR::clickSaveSlot); @@ -2523,6 +2102,7 @@ void GUI_MR::initStaticData() { GUI_V2_MENU_ITEM(_audioOptions.item[1], 0, 0, 160, 47, 116, 15, 0xFA, 0xFF, 5, 0xD0, 0xD1, 0xCF, -1, 24, 8, 49, 0x0000); GUI_V2_MENU_ITEM(_audioOptions.item[2], 0, 0, 160, 64, 116, 15, 0xFA, 0xFF, 5, 0xD0, 0xD1, 0xCF, -1, 39, 8, 66, 0x0000); GUI_V2_MENU_ITEM(_audioOptions.item[3], 1, 0, 152, 81, 116, 15, 0xFA, 0xFF, 5, 0xD0, 0xD1, 0xCF, -1, 47, 8, 83, 0x0000); + _audioOptions.item[3].callback = BUTTON_FUNCTOR(GUI_MR, this, &GUI_MR::toggleHeliumMode); GUI_V2_MENU_ITEM(_audioOptions.item[4], 1, 16, -1, 110, 92, 15, 0xFA, 0xFF, -1, 0xD0, 0xD1, 0xCF, -1, 0, 0, 0, 0x0000); _audioOptions.item[4].callback = clickQuitOptionsFunctor; for (int i = 5; i < 7; ++i) @@ -2592,5 +2172,15 @@ void GUI_MR::initStaticData() { _deathMenu.item[i].enabled = false; } +const int8 KyraEngine_MR::_albumWSAX[] = { + 0, 77, -50, 99, -61, 82, -58, 85, + -64, 80, -63, 88, -63, 88, -64, 0 +}; + +const int8 KyraEngine_MR::_albumWSAY[] = { + 0, -1, 3, 0, -1, 0, -2, 0, + -1, -2, 2, 2, -6, -6, -6, 0 +}; + } // End of namespace Kyra diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp index 980b762b23..f8eb10a85e 100644 --- a/engines/kyra/text.cpp +++ b/engines/kyra/text.cpp @@ -25,7 +25,7 @@ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/screen.h" #include "kyra/text.h" @@ -35,7 +35,7 @@ namespace Kyra { -TextDisplayer::TextDisplayer(KyraEngine *vm, Screen *screen) { +TextDisplayer::TextDisplayer(KyraEngine_v1 *vm, Screen *screen) { _screen = screen; _vm = vm; @@ -210,7 +210,7 @@ void TextDisplayer::printTalkTextMessage(const char *text, int x, int y, uint8 c calcWidestLineBounds(x1, x2, w, x); _talkCoords.x = x1; _talkCoords.w = w + 2; - _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage); + _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage, Screen::CR_NO_P_CHECK); int curPage = _screen->_curPage; _screen->_curPage = srcPage; for (int i = 0; i < lineCount; ++i) { diff --git a/engines/kyra/text.h b/engines/kyra/text.h index 5ae37e32ef..d45e5f9242 100644 --- a/engines/kyra/text.h +++ b/engines/kyra/text.h @@ -31,11 +31,11 @@ #include "kyra/screen.h" namespace Kyra { -class KyraEngine; +class KyraEngine_v1; class TextDisplayer { public: - TextDisplayer(KyraEngine *vm, Screen *screen); + TextDisplayer(KyraEngine_v1 *vm, Screen *screen); virtual ~TextDisplayer() {} int maxSubstringLen() const { return TALK_SUBSTRING_LEN; } @@ -60,7 +60,7 @@ public: bool printed() const { return _talkMessagePrinted; } protected: Screen *_screen; - KyraEngine *_vm; + KyraEngine_v1 *_vm; struct TalkCoords { uint16 y, x, w; diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index dd1796dd02..dd587c5112 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -107,8 +107,7 @@ char *TextDisplayer_HoF::preprocessString(const char *str) { int textWidth = _screen->getTextWidth(p); _screen->_charWidth = 0; - // longer text strings for German versions - int maxTextWidth = (_vm->language() == 2 ? 240 : 176); + int maxTextWidth = (_vm->language() == 0) ? 176 : 240; if (textWidth > maxTextWidth) { if (textWidth > (maxTextWidth*2)) { @@ -452,7 +451,7 @@ void KyraEngine_HoF::updateDlgBuffer() { filename[11] = suffix[_lang]; if (_dlgBuffer) - delete [] _dlgBuffer; + delete[] _dlgBuffer; _dlgBuffer = _res->fileData(filename, 0); } @@ -649,7 +648,7 @@ void KyraEngine_HoF::npcChatSequence(const char *str, int objectId, int vocHigh, } while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || skipFlag())) { - if (!speechEnabled() && chatAnimEndTime > _system->getMillis() || speechEnabled() && snd_voiceIsPlaying()) { + if ((!speechEnabled() && chatAnimEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) { _tim->resetFinishedFlag(); while (!_tim->finished() && !skipFlag() && !_quitFlag) { if (_currentTalkSections.TLKTim) diff --git a/engines/kyra/text_hof.h b/engines/kyra/text_hof.h index ef1f481c19..3da6e081f0 100644 --- a/engines/kyra/text_hof.h +++ b/engines/kyra/text_hof.h @@ -23,8 +23,8 @@ * */ -#ifndef KYRA_TEXT_V2_H -#define KYRA_TEXT_V2_H +#ifndef KYRA_TEXT_HOF_H +#define KYRA_TEXT_HOF_H #include "kyra/text.h" diff --git a/engines/kyra/text_v1.cpp b/engines/kyra/text_lok.cpp index 5534992c6a..f6b0407a75 100644 --- a/engines/kyra/text_v1.cpp +++ b/engines/kyra/text_lok.cpp @@ -23,17 +23,17 @@ * */ -#include "kyra/kyra_v1.h" -#include "kyra/screen_v1.h" +#include "kyra/kyra_lok.h" +#include "kyra/screen_lok.h" #include "kyra/text.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" #include "kyra/sprites.h" #include "kyra/timer.h" namespace Kyra { -void KyraEngine_v1::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum); +void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum); bool hasUpdatedNPCs = false; bool runLoop = true; bool drawText = textEnabled(); @@ -62,10 +62,8 @@ void KyraEngine_v1::waitForChatToFinish(int vocFile, int16 chatDuration, const c if (chatDuration != -1) chatDuration *= _tickLength; - if (vocFile != -1) { - snd_voiceWaitForFinish(); + if (vocFile != -1) snd_playVoiceFile(vocFile); - } _timer->disable(14); _timer->disable(18); @@ -154,7 +152,7 @@ void KyraEngine_v1::waitForChatToFinish(int vocFile, int16 chatDuration, const c //clearKyrandiaButtonIO(); } -void KyraEngine_v1::endCharacterChat(int8 charNum, int16 convoInitialized) { +void KyraEngine_LoK::endCharacterChat(int8 charNum, int16 convoInitialized) { _charSayUnk3 = -1; if (charNum > 4 && charNum < 11) { @@ -171,7 +169,7 @@ void KyraEngine_v1::endCharacterChat(int8 charNum, int16 convoInitialized) { } } -void KyraEngine_v1::restoreChatPartnerAnimFrame(int8 charNum) { +void KyraEngine_LoK::restoreChatPartnerAnimFrame(int8 charNum) { _talkingCharNum = -1; if (charNum > 0 && charNum < 5) { @@ -186,7 +184,7 @@ void KyraEngine_v1::restoreChatPartnerAnimFrame(int8 charNum) { _animator->updateAllObjectShapes(); } -void KyraEngine_v1::backupChatPartnerAnimFrame(int8 charNum) { +void KyraEngine_LoK::backupChatPartnerAnimFrame(int8 charNum) { _talkingCharNum = 0; if (charNum < 5 && charNum > 0) @@ -202,7 +200,7 @@ void KyraEngine_v1::backupChatPartnerAnimFrame(int8 charNum) { _animator->updateAllObjectShapes(); } -int8 KyraEngine_v1::getChatPartnerNum() { +int8 KyraEngine_LoK::getChatPartnerNum() { uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A}; int pos = 0; int partner = -1; @@ -224,7 +222,7 @@ int8 KyraEngine_v1::getChatPartnerNum() { return partner; } -int KyraEngine_v1::initCharacterChat(int8 charNum) { +int KyraEngine_LoK::initCharacterChat(int8 charNum) { int returnValue = 0; if (_talkingCharNum == -1) { @@ -258,8 +256,8 @@ int KyraEngine_v1::initCharacterChat(int8 charNum) { return returnValue; } -void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration); +void KyraEngine_LoK::characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration); uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 }; uint16 chatTicks; @@ -269,6 +267,8 @@ void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum if (_currentCharacter->sceneId == 210) return; + snd_voiceWaitForFinish(true); + convoInitialized = initCharacterChat(charNum); chatPartnerNum = getChatPartnerNum(); @@ -338,8 +338,8 @@ void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum endCharacterChat(charNum, convoInitialized); } -void KyraEngine_v1::drawSentenceCommand(const char *sentence, int color) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::drawSentenceCommand('%s', %i)", sentence, color); +void KyraEngine_LoK::drawSentenceCommand(const char *sentence, int color) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::drawSentenceCommand('%s', %i)", sentence, color); _screen->hideMouse(); _screen->fillRect(8, 143, 311, 152, 12); @@ -358,8 +358,8 @@ void KyraEngine_v1::drawSentenceCommand(const char *sentence, int color) { _fadeText = false; } -void KyraEngine_v1::updateSentenceCommand(const char *str1, const char *str2, int color) { - debugC(9, kDebugLevelMain, "KyraEngine_v1::updateSentenceCommand('%s', '%s', %i)", str1, str2, color); +void KyraEngine_LoK::updateSentenceCommand(const char *str1, const char *str2, int color) { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::updateSentenceCommand('%s', '%s', %i)", str1, str2, color); char sentenceCommand[500]; strncpy(sentenceCommand, str1, 500); if (str2) @@ -369,8 +369,8 @@ void KyraEngine_v1::updateSentenceCommand(const char *str1, const char *str2, in _screen->updateScreen(); } -void KyraEngine_v1::updateTextFade() { - debugC(9, kDebugLevelMain, "KyraEngine_v1::updateTextFade()"); +void KyraEngine_LoK::updateTextFade() { + debugC(9, kDebugLevelMain, "KyraEngine_LoK::updateTextFade()"); if (!_fadeText) return; diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index 35f91c1ccc..16c56da099 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -55,25 +55,26 @@ char *TextDisplayer_MR::preprocessString(const char *str) { int count = 0, offs = 0; if (textWidth > (3*maxTextWidth)) { count = getCharLength(p, textWidth/4); - offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + offs = dropCRIntoString(p, count, getCharLength(p, maxTextWidth)); p += count + offs; - } - + // No update of textWidth here + } + if (textWidth > (2*maxTextWidth)) { count = getCharLength(p, textWidth/3); - offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + offs = dropCRIntoString(p, count, getCharLength(p, maxTextWidth)); p += count + offs; textWidth = _screen->getTextWidth(p); } count = getCharLength(p, textWidth/2); - offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + offs = dropCRIntoString(p, count, getCharLength(p, maxTextWidth)); p += count + offs; textWidth = _screen->getTextWidth(p); if (textWidth > maxTextWidth) { count = getCharLength(p, textWidth/2); - offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count); + offs = dropCRIntoString(p, count, getCharLength(p, maxTextWidth)); } } @@ -131,6 +132,12 @@ int TextDisplayer_MR::dropCRIntoString(char *str, int minOffs, int maxOffs) { void TextDisplayer_MR::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font) { debugC(9, kDebugLevelMain, "TextDisplayer_MR::printText('%s', %d, %d, %d, %d, %d)", str, x, y, c0, c1, c2); + if (_vm->_albumChatActive) { + c0 = 0xEE; + c1 = 0xE3; + c2 = 0x00; + } + uint8 colorMap[] = { 0, 255, 240, 240 }; colorMap[3] = c1; _screen->setTextColor(colorMap, 0, 3); @@ -226,7 +233,7 @@ void KyraEngine_MR::objectChat(const char *str, int object, int vocHigh, int voc "MTFR00S.EMC", "MTFR00Q.EMC", "MTFR00E.EMC", "MTFR00T.EMC", "MTL00S.EMC", "MTL00Q.EMC", "MTL00E.EMC", "MTL00T.EMC", "MTR00S.EMC", "MTR00Q.EMC", "MTR00E.EMC", "MTR00T.EMC", - "MTA00S.EMC", "MTA00Q.EMC", "MTA00Q.EMC", "MTA00T.EMC" + "MTA00S.EMC", "MTA00Q.EMC", "MTA00E.EMC", "MTA00T.EMC" }; int chat = talkScriptTable[chatType + _mainCharacter.facing * 4]; @@ -496,6 +503,134 @@ void KyraEngine_MR::goodConscienceChatWaitToFinish() { } } +void KyraEngine_MR::albumChat(const char *str, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumChat('%s', %d, %d)", str, vocHigh, vocLow); + + _talkObjectList[1].x = 190; + _talkObjectList[1].y = 188; + + _chatVocHigh = _chatVocLow = -1; + _albumChatActive = true; + albumChatInit(str, 1, vocHigh, vocLow); + _albumChatActive = false; + + _chatText = str; + _chatObject = 1; + _screen->hideMouse(); + albumChatWaitToFinish(); + _screen->showMouse(); + + _chatText = 0; + _chatObject = -1; +} + +void KyraEngine_MR::albumChatInit(const char *str, int object, int vocHigh, int vocLow) { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumChatInit('%s', %d, %d, %d)", str, object, vocHigh, vocLow); + Common::String realString; + + while (*str) { + if (str[0] == '\\' && str[1] == 'r') { + realString += '\r'; + ++str; + } else { + realString += *str; + } + + ++str; + } + + str = realString.c_str(); + + str = _text->preprocessString(str); + int lineNum = _text->buildMessageSubstrings(str); + + int xPos = 0, yPos = 0; + + if (!object) { + int scale = getScale(_mainCharacter.x1, _mainCharacter.y1); + yPos = _mainCharacter.y1 - ((_mainCharacter.height * scale) >> 8) - 8; + xPos = _mainCharacter.x1; + } else { + yPos = _talkObjectList[object].y; + xPos = _talkObjectList[object].x; + } + + yPos -= lineNum * 10; + yPos = MAX(yPos, 0); + _text->_talkMessageY = yPos; + _text->_talkMessageH = lineNum*10; + + int width = _text->getWidestLineWidth(lineNum); + _text->calcWidestLineBounds(xPos, yPos, width, xPos); + _text->_talkCoords.x = xPos; + _text->_talkCoords.w = width + 2; + + _screen->hideMouse(); + + if (textEnabled()) { + objectChatPrintText(str, object); + _chatEndTime = _system->getMillis() + chatCalcDuration(str) * _tickLength; + } else { + _chatEndTime = _system->getMillis(); + } + + if (speechEnabled()) { + _chatVocHigh = vocHigh; + _chatVocLow = vocLow; + } else { + _chatVocHigh = _chatVocLow = -1; + } + + _screen->showMouse(); +} + +void KyraEngine_MR::albumChatWaitToFinish() { + debugC(9, kDebugLevelMain, "KyraEngine_MR::albumChatWaitToFinish()"); + if (_chatVocHigh) { + playVoice(_chatVocHigh, _chatVocLow); + _chatVocHigh = _chatVocLow = -1; + } + + bool running = true; + const uint32 endTime = _chatEndTime; + resetSkipFlag(); + + uint32 nextFrame = 0; + int frame = 12; + while (running && !_quitFlag) { + if (nextFrame < _system->getMillis()) { + ++frame; + if (frame > 22) + frame = 13; + + _album.wsa->setX(-100); + _album.wsa->setY(90); + _album.wsa->setDrawPage(2); + + albumRestoreRect(); + _album.wsa->displayFrame(frame, 0x4000); + albumUpdateRect(); + + nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; + } + + if (_album.nextPage != 14) + albumUpdateAnims(); + else + _screen->updateScreen(); + + const uint32 curTime = _system->getMillis(); + if ((textEnabled() && !speechEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || skipFlag()) { + snd_stopVoice(); + resetSkipFlag(); + nextFrame = curTime; + running = false; + } + + delay(10); + } +} + void KyraEngine_MR::malcolmSceneStartupChat() { debugC(9, kDebugLevelMain, "KyraEngine_MR::malcolmSceneStartupChat()"); diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp index 1f25f88c97..777871d65a 100644 --- a/engines/kyra/timer.cpp +++ b/engines/kyra/timer.cpp @@ -23,7 +23,7 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/timer.h" #include "common/func.h" @@ -34,7 +34,7 @@ namespace Kyra { namespace { struct TimerResync : public Common::UnaryFunction<TimerEntry&, void> { uint32 _tickLength, _curTime; - TimerResync(KyraEngine *vm, uint32 curTime) : _tickLength(vm->tickLength()), _curTime(curTime) {} + TimerResync(KyraEngine_v1 *vm, uint32 curTime) : _tickLength(vm->tickLength()), _curTime(curTime) {} void operator()(TimerEntry &entry) const { if (entry.lastUpdate < 0) { @@ -62,10 +62,32 @@ struct TimerEqual : public Common::UnaryFunction<const TimerEntry&, bool> { }; } // end of anonymous namespace +void TimerManager::pause(bool p) { + if (p) { + ++_isPaused; + + if (_isPaused == 1) { + _isPaused = true; + _pauseStart = _system->getMillis(); + } + } else if (!p && _isPaused > 0) { + --_isPaused; + + if (_isPaused == 0) { + const uint32 pausedTime = _system->getMillis() - _pauseStart; + _nextRun += pausedTime; + + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + pos->lastUpdate += pausedTime; + pos->nextRun += pausedTime; + } + } + } +} + void TimerManager::reset() { - for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) delete pos->func; - } _timers.clear(); } @@ -93,7 +115,7 @@ void TimerManager::addTimer(uint8 id, TimerFunc *func, int countdown, bool enabl void TimerManager::update() { debugC(9, kDebugLevelTimer, "TimerManager::update()"); - if (_system->getMillis() < _nextRun) + if (_system->getMillis() < _nextRun || _isPaused) return; _nextRun += 99999; @@ -121,8 +143,10 @@ void TimerManager::update() { void TimerManager::resync() { debugC(9, kDebugLevelTimer, "TimerManager::resync()"); + const uint32 curTime = _isPaused ? _pauseStart : _system->getMillis(); + _nextRun = 0; // force rerun - Common::for_each(_timers.begin(), _timers.end(), TimerResync(_vm, _system->getMillis())); + Common::for_each(_timers.begin(), _timers.end(), TimerResync(_vm, curTime)); } void TimerManager::resetNextRun() { @@ -225,7 +249,9 @@ void TimerManager::disable(uint8 id) { } void TimerManager::loadDataFromFile(Common::SeekableReadStream &file, int version) { - debugC(9, kDebugLevelTimer, "TimerManager::loadDataFromFile(%p, %d)", (const void*)&file, version); + debugC(9, kDebugLevelTimer, "TimerManager::loadDataFromFile(%p, %d)", (const void *)&file, version); + + const uint32 loadTime = _isPaused ? _pauseStart : _system->getMillis(); if (version <= 7) { _nextRun = 0; @@ -240,12 +266,11 @@ void TimerManager::loadDataFromFile(Common::SeekableReadStream &file, int versio timer->countdown = countdown; if (nextRun) { - timer->nextRun = nextRun + _system->getMillis(); + timer->nextRun = nextRun + loadTime; timer->lastUpdate = timer->nextRun - countdown * _vm->tickLength(); } else { - uint32 curTime = _system->getMillis(); - timer->nextRun = curTime; - timer->lastUpdate = curTime - countdown * _vm->tickLength(); + timer->nextRun = loadTime; + timer->lastUpdate = loadTime - countdown * _vm->tickLength(); } } else { warning("Loading timer data for non existing timer %d", i); @@ -272,14 +297,16 @@ void TimerManager::loadDataFromFile(Common::SeekableReadStream &file, int versio } void TimerManager::saveDataToFile(Common::WriteStream &file) const { - debugC(9, kDebugLevelTimer, "TimerManager::saveDataToFile(%p)", (const void*)&file); + debugC(9, kDebugLevelTimer, "TimerManager::saveDataToFile(%p)", (const void *)&file); + + const uint32 saveTime = _isPaused ? _pauseStart : _system->getMillis(); file.writeByte(count()); for (CIterator pos = _timers.begin(); pos != _timers.end(); ++pos) { file.writeByte(pos->id); file.writeByte(pos->enabled); file.writeSint32BE(pos->countdown); - file.writeSint32BE(pos->lastUpdate - _system->getMillis()); + file.writeSint32BE(pos->lastUpdate - saveTime); } } diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h index 0991f0a1b1..691bac3fb5 100644 --- a/engines/kyra/timer.h +++ b/engines/kyra/timer.h @@ -26,7 +26,7 @@ #ifndef KYRA_TIMER_H #define KYRA_TIMER_H -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "common/list.h" #include "common/stream.h" @@ -49,9 +49,11 @@ struct TimerEntry { class TimerManager { public: - TimerManager(KyraEngine *vm, OSystem *sys) : _vm(vm), _system(sys), _timers(), _nextRun(0) {} + TimerManager(KyraEngine_v1 *vm, OSystem *sys) : _vm(vm), _system(sys), _timers(), _nextRun(0), _isPaused(0), _pauseStart(0) {} ~TimerManager() { reset(); } + void pause(bool p); + void reset(); void addTimer(uint8 id, TimerFunc *func, int countdown, bool enabled); @@ -77,15 +79,26 @@ public: private: void resync(); - KyraEngine *_vm; + KyraEngine_v1 *_vm; OSystem *_system; Common::List<TimerEntry> _timers; uint32 _nextRun; + uint _isPaused; + uint32 _pauseStart; + typedef Common::List<TimerEntry>::iterator Iterator; typedef Common::List<TimerEntry>::const_iterator CIterator; }; +class PauseTimer { +public: + PauseTimer(TimerManager &timer) : _timer(timer) { _timer.pause(true); } + ~PauseTimer() { _timer.pause(false); } +private: + TimerManager &_timer; +}; + } // end of namespace Kyra #endif diff --git a/engines/kyra/timer_v1.cpp b/engines/kyra/timer_lok.cpp index f5e7c52ba1..69b93b54c3 100644 --- a/engines/kyra/timer_v1.cpp +++ b/engines/kyra/timer_lok.cpp @@ -23,20 +23,20 @@ * */ -#include "kyra/kyra.h" #include "kyra/kyra_v1.h" +#include "kyra/kyra_lok.h" #include "kyra/screen.h" -#include "kyra/animator_v1.h" +#include "kyra/animator_lok.h" #include "kyra/timer.h" #include "common/system.h" namespace Kyra { -#define TimerV1(x) new Common::Functor1Mem<int, void, KyraEngine_v1>(this, &KyraEngine_v1::x) +#define TimerV1(x) new Common::Functor1Mem<int, void, KyraEngine_LoK>(this, &KyraEngine_LoK::x) -void KyraEngine_v1::setupTimers() { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setupTimers()"); +void KyraEngine_LoK::setupTimers() { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::setupTimers()"); for (int i = 0; i <= 4; ++i) _timer->addTimer(i, 0, -1, 1); @@ -73,8 +73,8 @@ void KyraEngine_v1::setupTimers() { _timer->addTimer(33, TimerV1(updateAnimFlag2), 3, 1); } -void KyraEngine_v1::timerUpdateHeadAnims(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerUpdateHeadAnims(%i)", timerNum); +void KyraEngine_LoK::timerUpdateHeadAnims(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerUpdateHeadAnims(%i)", timerNum); static int8 currentFrame = 0; static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5, 4, 4, 6, 4, 8, 1, 9, 4, -1}; @@ -92,8 +92,8 @@ void KyraEngine_v1::timerUpdateHeadAnims(int timerNum) { _animator->animRefreshNPC(_talkingCharNum); } -void KyraEngine_v1::timerSetFlags1(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerSetFlags(%i)", timerNum); +void KyraEngine_LoK::timerSetFlags1(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerSetFlags(%i)", timerNum); if (_currentCharacter->sceneId == 0x1C) return; @@ -111,65 +111,65 @@ void KyraEngine_v1::timerSetFlags1(int timerNum) { } } -void KyraEngine_v1::timerFadeText(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerFadeText(%i)", timerNum); +void KyraEngine_LoK::timerFadeText(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerFadeText(%i)", timerNum); _fadeText = true; } -void KyraEngine_v1::updateAnimFlag1(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::updateAnimFlag1(%d)", timerNum); +void KyraEngine_LoK::updateAnimFlag1(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::updateAnimFlag1(%d)", timerNum); if (_brandonStatusBit & 2) { _brandonStatusBit0x02Flag = 1; } } -void KyraEngine_v1::updateAnimFlag2(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::updateAnimFlag2(%d)", timerNum); +void KyraEngine_LoK::updateAnimFlag2(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::updateAnimFlag2(%d)", timerNum); if (_brandonStatusBit & 0x20) { _brandonStatusBit0x20Flag = 1; } } -void KyraEngine_v1::setTextFadeTimerCountdown(int16 countdown) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setTextFadeTimerCountdown(%i)", countdown); +void KyraEngine_LoK::setTextFadeTimerCountdown(int16 countdown) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::setTextFadeTimerCountdown(%i)", countdown); if (countdown == -1) countdown = 32000; _timer->setCountdown(31, countdown*60); } -void KyraEngine_v1::timerSetFlags2(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerSetFlags2(%i)", timerNum); +void KyraEngine_LoK::timerSetFlags2(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerSetFlags2(%i)", timerNum); if (!((uint32*)(_flagsTable+0x2D))[timerNum]) ((uint32*)(_flagsTable+0x2D))[timerNum] = 1; } -void KyraEngine_v1::timerCheckAnimFlag1(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerCheckAnimFlag1(%i)", timerNum); +void KyraEngine_LoK::timerCheckAnimFlag1(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerCheckAnimFlag1(%i)", timerNum); if (_brandonStatusBit & 0x20) { checkAmuletAnimFlags(); _timer->setCountdown(18, -1); } } -void KyraEngine_v1::timerCheckAnimFlag2(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerCheckAnimFlag2(%i)", timerNum); +void KyraEngine_LoK::timerCheckAnimFlag2(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerCheckAnimFlag2(%i)", timerNum); if (_brandonStatusBit & 0x2) { checkAmuletAnimFlags(); _timer->setCountdown(14, -1); } } -void KyraEngine_v1::timerRedrawAmulet(int timerNum) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerRedrawAmulet(%i)", timerNum); +void KyraEngine_LoK::timerRedrawAmulet(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::timerRedrawAmulet(%i)", timerNum); if (queryGameFlag(0xF1)) { drawAmulet(); _timer->setCountdown(19, -1); } } -void KyraEngine_v1::setWalkspeed(uint8 newSpeed) { - debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setWalkspeed(%i)", newSpeed); +void KyraEngine_LoK::setWalkspeed(uint8 newSpeed) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_LoK::setWalkspeed(%i)", newSpeed); static const uint8 speeds[] = { 11, 9, 6, 5, 3 }; assert(newSpeed < ARRAYSIZE(speeds)); diff --git a/engines/kyra/timer_mr.cpp b/engines/kyra/timer_mr.cpp index 53865ba0e3..37a910ccf2 100644 --- a/engines/kyra/timer_mr.cpp +++ b/engines/kyra/timer_mr.cpp @@ -64,7 +64,25 @@ void KyraEngine_MR::timerRunSceneScript7(int arg) { void KyraEngine_MR::timerFleaDeath(int arg) { debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_MR::timerFleaDeath(%d)", arg); - warning("STUB timerFleaDeath"); + _timer->setCountdown(4, 5400); + saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME"); + _screen->hideMouse(); + _timer->disable(4); + runAnimationScript("FLEADTH1.EMC", 0, 0, 1, 1); + runAnimationScript("FLEADTH2.EMC", 0, 0, 1, 0); + showBadConscience(); + delay(60, true); + const char *str1 = (const char *)getTableEntry(_cCodeFile, 130); + const char *str2 = (const char *)getTableEntry(_cCodeFile, 131); + if (str1 && str2) { + badConscienceChat(str1, 204, 130); + badConscienceChat(str2, 204, 131); + } + delay(60, true); + hideBadConscience(); + runAnimationScript("FLEADTH3.EMC", 0, 0, 0, 1); + _deathHandler = 9; + _screen->showMouse(); } void KyraEngine_MR::setWalkspeed(uint8 speed) { diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index db7cad941b..3d18f27c7e 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -42,7 +42,7 @@ namespace Kyra { -VQAMovie::VQAMovie(KyraEngine *vm, OSystem *system) { +VQAMovie::VQAMovie(KyraEngine_v1 *vm, OSystem *system) { _system = system; _vm = vm; _opened = false; @@ -69,7 +69,7 @@ void *VQAMovie::allocBuffer(int num, uint32 size) { * We could use realloc() here, but we don't actually need the * old contents of the buffer. */ - delete [] _buffers[num].data; + delete[] _buffers[num].data; _buffers[num].data = new uint8[size]; _buffers[num].size = size; } @@ -81,7 +81,7 @@ void *VQAMovie::allocBuffer(int num, uint32 size) { void VQAMovie::freeBuffers() { for (int i = 0; i < ARRAYSIZE(_buffers); i++) { - delete [] _buffers[i].data; + delete[] _buffers[i].data; _buffers[i].data = NULL; _buffers[i].size = 0; } @@ -356,15 +356,14 @@ bool VQAMovie::open(const char *filename) { void VQAMovie::close() { debugC(9, kDebugLevelMovie, "VQAMovie::close()"); if (_opened) { - delete [] _frameInfo; - delete [] _frame; - delete [] _codeBook; - delete [] _partialCodeBook; - delete [] _vectorPointers; + delete[] _frameInfo; + delete[] _frame; + delete[] _codeBook; + delete[] _partialCodeBook; + delete[] _vectorPointers; - if (_vm->_mixer->isSoundHandleActive(_sound)) { + if (_vm->_mixer->isSoundHandleActive(_sound)) _vm->_mixer->stopHandle(_sound); - } _frameInfo = NULL; _frame = NULL; @@ -655,11 +654,10 @@ void VQAMovie::play() { while (1) { uint32 elapsedTime; - if (_vm->_mixer->isSoundHandleActive(_sound)) { + if (_vm->_mixer->isSoundHandleActive(_sound)) elapsedTime = _vm->_mixer->getSoundElapsedTime(_sound); - } else { + else elapsedTime = _system->getMillis() - startTick; - } if (elapsedTime >= (i * 1000) / _header.frameRate) break; diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h index 35f7d78004..f600f008b7 100644 --- a/engines/kyra/vqa.h +++ b/engines/kyra/vqa.h @@ -30,11 +30,11 @@ class OSystem; namespace Kyra { -class KyraEngine; +class KyraEngine_v1; class VQAMovie { public: - VQAMovie(KyraEngine *vm, OSystem *system); + VQAMovie(KyraEngine_v1 *vm, OSystem *system); ~VQAMovie(); bool opened() { return _opened; } @@ -54,7 +54,7 @@ public: protected: OSystem *_system; - KyraEngine *_vm; + KyraEngine_v1 *_vm; bool _opened; int _x, _y; diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp index 764327d701..110755c3ba 100644 --- a/engines/kyra/wsamovie.cpp +++ b/engines/kyra/wsamovie.cpp @@ -27,7 +27,7 @@ #include "common/endian.h" #include "common/system.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_v2.h" #include "kyra/screen.h" #include "kyra/screen_v2.h" @@ -35,11 +35,11 @@ #include "kyra/resource.h" namespace Kyra { -WSAMovieV1::WSAMovieV1(KyraEngine *vm) : Movie(vm) {} -WSAMovieV1::~WSAMovieV1() { close(); } +WSAMovie_v1::WSAMovie_v1(KyraEngine_v1 *vm) : Movie(vm) {} +WSAMovie_v1::~WSAMovie_v1() { close(); } -int WSAMovieV1::open(const char *filename, int offscreenDecode, uint8 *palBuf) { - debugC(9, kDebugLevelMovie, "WSAMovieV1::open('%s', %d, %p)", filename, offscreenDecode, (const void *)palBuf); +int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) { + debugC(9, kDebugLevelMovie, "WSAMovie_v1::open('%s', %d, %p)", filename, offscreenDecode, (const void *)palBuf); close(); uint32 flags = 0; @@ -117,25 +117,25 @@ int WSAMovieV1::open(const char *filename, int offscreenDecode, uint8 *palBuf) { if (firstFrame) Screen::decodeFrame4(_frameData, _deltaBuffer, _deltaBufferSize); - delete [] p; + delete[] p; _opened = true; return _numFrames; } -void WSAMovieV1::close() { - debugC(9, kDebugLevelMovie, "WSAMovieV1::close()"); +void WSAMovie_v1::close() { + debugC(9, kDebugLevelMovie, "WSAMovie_v1::close()"); if (_opened) { - delete [] _deltaBuffer; - delete [] _offscreenBuffer; - delete [] _frameOffsTable; - delete [] _frameData; + delete[] _deltaBuffer; + delete[] _offscreenBuffer; + delete[] _frameOffsTable; + delete[] _frameData; _opened = false; } } -void WSAMovieV1::displayFrame(int frameNum, ...) { - debugC(9, kDebugLevelMovie, "WSAMovieV1::displayFrame(%d, ...)", frameNum); +void WSAMovie_v1::displayFrame(int frameNum, ...) { + debugC(9, kDebugLevelMovie, "WSAMovie_v1::displayFrame(%d, ...)", frameNum); if (frameNum >= _numFrames || !_opened) return; @@ -198,8 +198,8 @@ void WSAMovieV1::displayFrame(int frameNum, ...) { _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer); } -void WSAMovieV1::processFrame(int frameNum, uint8 *dst) { - debugC(9, kDebugLevelMovie, "WSAMovieV1::processFrame(%d, %p)", frameNum, (const void *)dst); +void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) { + debugC(9, kDebugLevelMovie, "WSAMovie_v1::processFrame(%d, %p)", frameNum, (const void *)dst); if (!_opened) return; assert(frameNum <= _numFrames); @@ -213,11 +213,11 @@ void WSAMovieV1::processFrame(int frameNum, uint8 *dst) { #pragma mark - -WSAMovieAmiga::WSAMovieAmiga(KyraEngine *vm) : WSAMovieV1(vm), _buffer(0) {} +WSAMovieAmiga::WSAMovieAmiga(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _buffer(0) {} int WSAMovieAmiga::open(const char *filename, int offscreenDecode, uint8 *palBuf) { debugC(9, kDebugLevelMovie, "WSAMovieAmiga::open('%s', %d, %p)", filename, offscreenDecode, (const void *)palBuf); - int res = WSAMovieV1::open(filename, offscreenDecode, palBuf); + int res = WSAMovie_v1::open(filename, offscreenDecode, palBuf); if (!res) return 0; @@ -230,10 +230,10 @@ int WSAMovieAmiga::open(const char *filename, int offscreenDecode, uint8 *palBuf void WSAMovieAmiga::close() { debugC(9, kDebugLevelMovie, "WSAMovieAmiga::close()"); if (_opened) { - delete [] _buffer; + delete[] _buffer; _buffer = 0; } - WSAMovieV1::close(); + WSAMovie_v1::close(); } void WSAMovieAmiga::displayFrame(int frameNum, ...) { @@ -342,10 +342,10 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { #pragma mark - -WSAMovieV2::WSAMovieV2(KyraEngine *vm, Screen_v2 *screen) : WSAMovieV1(vm), _screen(screen), _xAdd(0), _yAdd(0) {} +WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen) : WSAMovie_v1(vm), _screen(screen), _xAdd(0), _yAdd(0) {} -int WSAMovieV2::open(const char *filename, int unk1, uint8 *palBuf) { - debugC(9, kDebugLevelMovie, "WSAMovieV2::open('%s', %d, %p)", filename, unk1, (const void *)palBuf); +int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { + debugC(9, kDebugLevelMovie, "WSAMovie_v2::open('%s', %d, %p)", filename, unk1, (const void *)palBuf); close(); uint32 flags = 0; @@ -423,14 +423,14 @@ int WSAMovieV2::open(const char *filename, int unk1, uint8 *palBuf) { if (firstFrame) Screen::decodeFrame4(_frameData, _deltaBuffer, _deltaBufferSize); - delete [] p; + delete[] p; _opened = true; return _numFrames; } -void WSAMovieV2::displayFrame(int frameNum, ...) { - debugC(9, kDebugLevelMovie, "WSAMovieV2::displayFrame(%d, ...)", frameNum); +void WSAMovie_v2::displayFrame(int frameNum, ...) { + debugC(9, kDebugLevelMovie, "WSAMovie_v2::displayFrame(%d, ...)", frameNum); if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h index d1f3465c07..36cd75b1ab 100644 --- a/engines/kyra/wsamovie.h +++ b/engines/kyra/wsamovie.h @@ -32,12 +32,12 @@ class SoundHandle; } // end of namespace Audio namespace Kyra { -class KyraEngine; +class KyraEngine_v1; class Screen_v2; class Movie { public: - Movie(KyraEngine *vm) : _vm(vm), _opened(false), _x(-1), _y(-1), _drawPage(-1) {} + Movie(KyraEngine_v1 *vm) : _vm(vm), _opened(false), _x(-1), _y(-1), _drawPage(-1) {} virtual ~Movie() {} virtual bool opened() { return _opened; } @@ -53,17 +53,17 @@ public: virtual void setY(int y) { _y = y; } virtual void setDrawPage(int page) { _drawPage = page; } protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; bool _opened; int _x, _y; int _drawPage; }; -class WSAMovieV1 : public Movie { +class WSAMovie_v1 : public Movie { public: - WSAMovieV1(KyraEngine *vm); - virtual ~WSAMovieV1(); + WSAMovie_v1(KyraEngine_v1 *vm); + virtual ~WSAMovie_v1(); virtual int open(const char *filename, int offscreen, uint8 *palette); virtual void close(); @@ -94,9 +94,9 @@ protected: uint8 *_frameData; }; -class WSAMovieAmiga : public WSAMovieV1 { +class WSAMovieAmiga : public WSAMovie_v1 { public: - WSAMovieAmiga(KyraEngine *vm); + WSAMovieAmiga(KyraEngine_v1 *vm); int open(const char *filename, int offscreen, uint8 *palette); void close(); @@ -107,9 +107,9 @@ private: uint8 *_buffer; }; -class WSAMovieV2 : public WSAMovieV1 { +class WSAMovie_v2 : public WSAMovie_v1 { public: - WSAMovieV2(KyraEngine *vm, Screen_v2 *scren); + WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *scren); int open(const char *filename, int unk1, uint8 *palette); diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp index c87f81618a..f9b31c21c5 100644 --- a/engines/lure/game.cpp +++ b/engines/lure/game.cpp @@ -167,6 +167,7 @@ void Game::execute() { if (system.getMillis() > timerVal + GAME_FRAME_DELAY) { timerVal = system.getMillis(); nextFrame(); + res.delayList().tick(); Sound.musicInterface_ContinuePlaying(); } @@ -177,8 +178,6 @@ void Game::execute() { tickCheck(); } - res.delayList().tick(); - while (events.pollEvent()) { if (events.type() == Common::EVENT_KEYDOWN) { uint16 roomNum = room.roomNumber(); diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp index de213b4f5a..06d3b1984e 100644 --- a/engines/lure/lure.cpp +++ b/engines/lure/lure.cpp @@ -154,6 +154,16 @@ int LureEngine::go() { return 0; } +void LureEngine::pauseEngineIntern(bool pause) { + Engine::pauseEngineIntern(pause); + + if (pause) { + Sound.pause(); + } else { + Sound.resume(); + } +} + void LureEngine::quitGame() { _system->quit(); } diff --git a/engines/lure/lure.h b/engines/lure/lure.h index fa70abc1f0..d66f446247 100644 --- a/engines/lure/lure.h +++ b/engines/lure/lure.h @@ -69,6 +69,7 @@ public: virtual int init(); virtual int go(); + virtual void pauseEngineIntern(bool pause); void quitGame(); Disk &disk() { return *_disk; } diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp index ce35b50243..f2997d5d17 100644 --- a/engines/lure/res.cpp +++ b/engines/lure/res.cpp @@ -85,7 +85,7 @@ void Resources::freeData() { delete _talkDialogData; delete _messagesData; delete _cursors; - delete [] _charOffsets; + delete[] _charOffsets; } struct AnimRecordTemp { diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp index fcb6b874be..de09f982d1 100644 --- a/engines/lure/res_struct.cpp +++ b/engines/lure/res_struct.cpp @@ -760,10 +760,8 @@ RoomExitCoordinateData &RoomExitCoordinates::getData(uint16 destRoomNumber) { // The following classes hold any sequence offsets that are being delayed SequenceDelayData::SequenceDelayData(uint16 delay, uint16 seqOffset, bool canClearFlag) { - OSystem &system = *g_system; - - // The delay is in number of seconds - timeoutCtr = system.getMillis() + delay * 1000; + // The delay is in number of seconds - convert it to remaining milliseconds + timeoutCtr = delay * 1000; sequenceOffset = seqOffset; canClear = canClearFlag; } @@ -784,21 +782,23 @@ void SequenceDelayList::add(uint16 delay, uint16 seqOffset, bool canClear) { } void SequenceDelayList::tick() { - uint32 currTime = g_system->getMillis(); SequenceDelayList::iterator i; - debugC(ERROR_DETAILED, kLureDebugScripts, "Delay List check start at time %d", currTime); + debugC(ERROR_DETAILED, kLureDebugScripts, "Delay List check start at time %d", + g_system->getMillis()); for (i = begin(); i != end(); i++) { SequenceDelayData *entry = (*i).get(); debugC(ERROR_DETAILED, kLureDebugScripts, "Delay List check %xh at time %d", entry->sequenceOffset, entry->timeoutCtr); - if (currTime >= entry->timeoutCtr) { + if (entry->timeoutCtr <= GAME_FRAME_DELAY) { // Timeout reached - delete entry from list and execute the sequence uint16 seqOffset = entry->sequenceOffset; erase(i); Script::execute(seqOffset); return; + } else { + entry->timeoutCtr -= GAME_FRAME_DELAY; } } } @@ -816,14 +816,12 @@ void SequenceDelayList::clear(bool forceClear) { } void SequenceDelayList::saveToStream(WriteStream *stream) { - uint32 currTime = g_system->getMillis(); SequenceDelayList::iterator i; for (i = begin(); i != end(); ++i) { SequenceDelayData *entry = (*i).get(); stream->writeUint16LE(entry->sequenceOffset); - stream->writeUint32LE((currTime > entry->timeoutCtr ) ? 0 : - entry->timeoutCtr - currTime); + stream->writeUint32LE(entry->timeoutCtr); stream->writeByte(entry->canClear); } @@ -833,10 +831,9 @@ void SequenceDelayList::saveToStream(WriteStream *stream) { void SequenceDelayList::loadFromStream(ReadStream *stream) { clear(true); uint16 seqOffset; - uint32 currTime = g_system->getMillis(); while ((seqOffset = stream->readUint16LE()) != 0) { - uint32 delay = currTime + stream->readUint32LE(); + uint32 delay = stream->readUint32LE(); bool canClear = stream->readByte() != 0; push_back(SequenceDelayList::value_type(SequenceDelayData::load(delay, seqOffset, canClear))); } @@ -1008,8 +1005,8 @@ RandomActionSet::RandomActionSet(uint16 *&offset) { } RandomActionSet::~RandomActionSet() { - delete [] _types; - delete [] _ids; + delete[] _types; + delete[] _ids; } RandomActionSet *RandomActionList::getRoom(uint16 roomNumber) { diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index 6480428661..729af6c40f 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -1110,7 +1110,7 @@ void Converse::setValue(int32 offset, int32 value) { _variables[hashOffset] = value; } -const int32 Converse::getValue(int32 offset) { +int32 Converse::getValue(int32 offset) { char hashOffset[10]; sprintf(hashOffset, "%i", offset); ConvVarHashMap::const_iterator entry = _variables.find(hashOffset); diff --git a/engines/m4/converse.h b/engines/m4/converse.h index bea90d9ddf..4bd4524029 100644 --- a/engines/m4/converse.h +++ b/engines/m4/converse.h @@ -171,7 +171,7 @@ public: ConvEntry *getNode(int32 index) { return _convNodes[index]; } void setValue(int32 offset, int32 value); - const int32 getValue(int32 offset); + int32 getValue(int32 offset); bool evaluateCondition(int32 leftVal, int32 op, int32 rightVal); bool performAction(EntryAction *action); /* diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp index c9b9a44f23..119e7297cf 100644 --- a/engines/m4/font.cpp +++ b/engines/m4/font.cpp @@ -192,7 +192,7 @@ int32 Font::write(M4Surface *surface, const char *text, int x, int y, int width, while (*text) { - char theChar = (*text++) & 0x7F; + unsigned char theChar = (*text++) & 0x7F; int charWidth = _charWidths[theChar]; if (charWidth > 0) { diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 6707639d1c..b2c0eda1ce 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -396,10 +396,12 @@ int M4Engine::goM4() { // Show intro - if (getGameType() == GType_Burger) + if (getGameType() == GType_Burger) { _kernel->newRoom = TITLE_SCENE_BURGER; - else + } else { _scene->getBackgroundSurface()->loadBackgroundRiddle("main menu"); + _ws->setBackgroundSurface(_scene->getBackgroundSurface()); + } _viewManager->addView(_scene); diff --git a/engines/m4/script.h b/engines/m4/script.h index a59bf46e86..2a937040e9 100644 --- a/engines/m4/script.h +++ b/engines/m4/script.h @@ -300,7 +300,8 @@ public: const T& toData(const ScriptValue &value) { printf("ScriptInterpreter::toData() index = %d; type = %d; max = %d\n", value.value, _data[value.value]->type, _data.size()); assert((uint32)value.value < _data.size()); - return *(_dataCache->load<T>(_scriptFile, _data[value.value]->offset)); + T *result = _dataCache->load<T>(_scriptFile, _data[value.value]->offset); + return *result; } const char *getGlobalString(int index) const { diff --git a/engines/made/database.cpp b/engines/made/database.cpp index a7970a2e27..55e0e90732 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -39,7 +39,7 @@ namespace Made { < 0x7FFE object */ -Object::Object() { +Object::Object() : _objData(NULL), _freeData(false) { } Object::~Object() { @@ -47,82 +47,6 @@ Object::~Object() { delete[] _objData; } -int Object::loadVersion2(Common::SeekableReadStream &source) { - _freeData = true; - uint16 type = source.readUint16LE(); - if (type == 0x7FFF) { - _objSize = source.readUint16LE(); - } else if (type == 0x7FFE) { - _objSize = source.readUint16LE() * 2; - } else if (type < 0x7FFE) { - byte count1 = source.readByte(); - byte count2 = source.readByte(); - _objSize = (count1 + count2) * 2; - } - source.seek(-4, SEEK_CUR); - _objSize += 6; - _objData = new byte[_objSize]; - WRITE_LE_UINT16(_objData, 1); - source.read(_objData + 2, _objSize - 2); - return _objSize - 2; -} - -int Object::loadVersion3(Common::SeekableReadStream &source) { - _freeData = true; - source.readUint16LE(); // skip flags - uint16 type = source.readUint16LE(); - if (type == 0x7FFF) { - _objSize = source.readUint16LE(); - } else if (type == 0x7FFE) { - _objSize = source.readUint16LE() * 2; - } else if (type < 0x7FFE) { - byte count1 = source.readByte(); - byte count2 = source.readByte(); - _objSize = (count1 + count2) * 2; - } - source.seek(-6, SEEK_CUR); - _objSize += 6; - _objData = new byte[_objSize]; - source.read(_objData, _objSize); - return _objSize; -} - -int Object::loadVersion3(byte *source) { - _objData = source; - _freeData = false; - if (getClass() < 0x7FFE) { - _objSize = (getCount1() + getCount2()) * 2; - } else { - _objSize = getSize(); - } - _objSize += 6; - return _objSize; -} - -uint16 Object::getFlags() const { - return READ_LE_UINT16(_objData); -} - -uint16 Object::getClass() const { - return READ_LE_UINT16(_objData + 2); -} - -uint16 Object::getSize() const { - return READ_LE_UINT16(_objData + 4); -} - -byte Object::getCount1() const { - return _objData[4]; -} - -byte Object::getCount2() const { - return _objData[5]; -} - -byte *Object::getData() { - return _objData + 6; -} - const char *Object::getString() { if (getClass() == 0x7FFF) return (const char*)getData(); @@ -195,15 +119,140 @@ void Object::dump(const char *filename) { */ } +int ObjectV2::load(Common::SeekableReadStream &source) { + + if (_freeData && _objData) + delete[] _objData; + + _freeData = true; + + byte header[4]; + source.read(header, 4); + + uint16 type = READ_LE_UINT16(header); + if (type == 0x7FFF) { + _objSize = READ_LE_UINT16(header + 2); + } else if (type == 0x7FFE) { + _objSize = READ_LE_UINT16(header + 2) * 2; + } else if (type < 0x7FFE) { + byte count1 = header[2]; + byte count2 = header[3]; + _objSize = (count1 + count2) * 2; + } + _objSize += 4; + _objData = new byte[_objSize]; + memcpy(_objData, header, 4); + source.read(_objData + 4, _objSize - 4); + + return _objSize; + +} + +int ObjectV2::load(byte *source) { + // Not implemented/used for version 2 objects + return 0; +} + +int ObjectV2::save(Common::WriteStream &dest) { + dest.write(_objData, _objSize); + return 0; +} + +uint16 ObjectV2::getFlags() { + return 1; +} + +uint16 ObjectV2::getClass() { + return READ_LE_UINT16(_objData); +} + +uint16 ObjectV2::getSize() { + return READ_LE_UINT16(_objData + 2); +} + +byte ObjectV2::getCount1() { + return _objData[2]; +} + +byte ObjectV2::getCount2() { + return _objData[3]; +} + +byte *ObjectV2::getData() { + return _objData + 4; +} + +int ObjectV3::load(Common::SeekableReadStream &source) { + + _freeData = true; + source.readUint16LE(); // skip flags + uint16 type = source.readUint16LE(); + if (type == 0x7FFF) { + _objSize = source.readUint16LE(); + } else if (type == 0x7FFE) { + _objSize = source.readUint16LE() * 2; + } else if (type < 0x7FFE) { + byte count1 = source.readByte(); + byte count2 = source.readByte(); + _objSize = (count1 + count2) * 2; + } + source.seek(-6, SEEK_CUR); + _objSize += 6; + _objData = new byte[_objSize]; + source.read(_objData, _objSize); + return _objSize; + +} + +int ObjectV3::load(byte *source) { + _objData = source; + _freeData = false; + if (getClass() < 0x7FFE) { + _objSize = (getCount1() + getCount2()) * 2; + } else { + _objSize = getSize(); + } + _objSize += 6; + return _objSize; +} + +int ObjectV3::save(Common::WriteStream &dest) { + // Not implemented/used for version 3 objects + return 0; +} + +uint16 ObjectV3::getFlags() { + return READ_LE_UINT16(_objData); +} + +uint16 ObjectV3::getClass() { + return READ_LE_UINT16(_objData + 2); +} + +uint16 ObjectV3::getSize() { + return READ_LE_UINT16(_objData + 4); +} + +byte ObjectV3::getCount1() { + return _objData[4]; +} + +byte ObjectV3::getCount2() { + return _objData[5]; +} + +byte *ObjectV3::getData() { + return _objData + 6; +} + + + GameDatabase::GameDatabase(MadeEngine *vm) : _vm(vm) { - _gameText = NULL; } GameDatabase::~GameDatabase() { if (_gameState) delete[] _gameState; - if (_gameText) - delete[] _gameText; } void GameDatabase::open(const char *filename) { @@ -224,19 +273,85 @@ void GameDatabase::openFromRed(const char *redFilename, const char *filename) { delete fileS; } -void GameDatabase::load(Common::SeekableReadStream &sourceS) { +int16 GameDatabase::getVar(int16 index) { + return (int16)READ_LE_UINT16(_gameState + index * 2); +} + +void GameDatabase::setVar(int16 index, int16 value) { + WRITE_LE_UINT16(_gameState + index * 2, value); +} + +const char *GameDatabase::getObjectString(int16 index) { + Object *obj = getObject(index); + if (obj) + return obj->getString(); + else + return ""; +} - if (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_LGOP2) { - debug(2, "loading version 2 dat"); - loadVersion2(sourceS); - } else if (_vm->getGameID() == GID_RTZ) { - debug(2, "loading version 3 dat"); - loadVersion3(sourceS); +void GameDatabase::setObjectString(int16 index, const char *str) { + Object *obj = getObject(index); + if (obj) + obj->setString(str); +} + +int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) { + + if (objectIndex == 0) + return 0; + + int16 propertyFlag; + int16 *property = findObjectProperty(objectIndex, propertyId, propertyFlag); + + if (property) { + return (int16)READ_LE_UINT16(property); + } else { + return 0; } } -void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { +int16 GameDatabase::setObjectProperty(int16 objectIndex, int16 propertyId, int16 value) { + + if (objectIndex == 0) + return 0; + + int16 propertyFlag; + int16 *property = findObjectProperty(objectIndex, propertyId, propertyFlag); + + if (property) { + if (propertyFlag == 1) { + WRITE_LE_UINT16(property, value); + } else { + warning("GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n", + objectIndex, propertyId, value); + } + return value; + } else { + return 0; + } + +} + +void GameDatabase::dumpObject(int16 index) { + Object *obj = getObject(index); + char fn[512]; + sprintf(fn, "obj%04X.0", index); + obj->dump(fn); +} + + +/* GameDatabaseV2 */ + +GameDatabaseV2::GameDatabaseV2(MadeEngine *vm) : GameDatabase(vm), _gameText(NULL) { +} + +GameDatabaseV2::~GameDatabaseV2() { + if (_gameText) + delete[] _gameText; +} + +void GameDatabaseV2::load(Common::SeekableReadStream &sourceS) { // TODO: Read/verifiy header @@ -256,8 +371,9 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { debug(2, "textOffs = %08X; textSize = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", textOffs, textSize, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize); - _gameState = new byte[_gameStateSize]; + _gameState = new byte[_gameStateSize + 2]; memset(_gameState, 0, _gameStateSize); + setVar(1, objectCount); sourceS.seek(textOffs); _gameText = new char[textSize]; @@ -269,145 +385,52 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { sourceS.seek(objectsOffs); for (uint32 i = 0; i < objectCount; i++) { - Object *obj = new Object(); - int objSize = obj->loadVersion2(sourceS); - objSize = objSize % 2; + Object *obj = new ObjectV2(); + int objSize = obj->load(sourceS); // objects are aligned on 2-byte-boundaries, skip unused bytes - sourceS.skip(objSize); + sourceS.skip(objSize % 2); _objects.push_back(obj); } } -void GameDatabase::loadVersion3(Common::SeekableReadStream &sourceS) { - - // TODO: Read/verifiy header - - sourceS.seek(0x1E); - - uint32 objectIndexOffs = sourceS.readUint32LE(); - uint16 objectCount = sourceS.readUint16LE(); - uint32 gameStateOffs = sourceS.readUint32LE(); - _gameStateSize = sourceS.readUint32LE(); - uint32 objectsOffs = sourceS.readUint32LE(); - uint32 objectsSize = sourceS.readUint32LE(); - _mainCodeObjectIndex = sourceS.readUint16LE(); - - debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize); - - _gameState = new byte[_gameStateSize]; - sourceS.seek(gameStateOffs); - sourceS.read(_gameState, _gameStateSize); - - Common::Array<uint32> objectOffsets; - sourceS.seek(objectIndexOffs); - for (uint32 i = 0; i < objectCount; i++) - objectOffsets.push_back(sourceS.readUint32LE()); - - for (uint32 i = 0; i < objectCount; i++) { - Object *obj = new Object(); - - // The LSB indicates if it's a constant or variable object. - // Constant objects are loaded from disk, while variable objects exist - // in the _gameState buffer. - - debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]); - - if (objectOffsets[i] & 1) { - debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1); - sourceS.seek(objectsOffs + objectOffsets[i] - 1); - obj->loadVersion3(sourceS); - } else { - debug(2, "-> var\n"); - obj->loadVersion3(_gameState + objectOffsets[i]); - } - _objects.push_back(obj); - } - -} - -bool GameDatabase::getSavegameDescription(const char *filename, Common::String &description) { - - Common::InSaveFile *in; - - if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { - return false; - } - - char desc[64]; - - in->skip(4); // TODO: Verify marker 'SGAM' - in->skip(4); // TODO: Verify size - in->skip(2); // TODO: Verify version - in->read(desc, 64); - description = desc; - - printf("description = %s\n", description.c_str()); fflush(stdout); - - delete in; - - return true; - +bool GameDatabaseV2::getSavegameDescription(const char *filename, Common::String &description) { + // Not used in version 2 games + return false; } -int16 GameDatabase::savegame(const char *filename, const char *description, int16 version) { - +int16 GameDatabaseV2::savegame(const char *filename, const char *description, int16 version) { Common::OutSaveFile *out; - + int16 result = 0; if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); return 6; } - - uint32 size = 4 + 4 + 2 + _gameStateSize; - char desc[64]; - - strncpy(desc, description, 64); - - out->writeUint32BE(MKID_BE('SGAM')); - out->writeUint32LE(size); - out->writeUint16LE(version); - out->write(desc, 64); - out->write(_gameState, _gameStateSize); - + // Variable 0 is not saved + out->write(_gameState + 2, _gameStateSize - 2); + for (uint i = 0; i < _objects.size(); i++) + _objects[i]->save(*out); delete out; - - return 0; - + return result; } -int16 GameDatabase::loadgame(const char *filename, int16 version) { - +int16 GameDatabaseV2::loadgame(const char *filename, int16 version) { Common::InSaveFile *in; - + int16 result = 0; if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { warning("Can't open file '%s', game not loaded", filename); return 1; } - - //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; - - in->skip(4); // TODO: Verify marker 'SGAM' - in->skip(4); // TODO: Verify size - in->skip(2); // TODO: Verify version - in->skip(64); // skip savegame description - in->read(_gameState, _gameStateSize); - + // Variable 0 is not loaded + in->read(_gameState + 2, _gameStateSize - 2); + for (uint i = 0; i < _objects.size(); i++) { + _objects[i]->load(*in); + } delete in; - - return 0; - + return result; } -int16 GameDatabase::getVar(int16 index) { - return (int16)READ_LE_UINT16(_gameState + index * 2); -} - -void GameDatabase::setVar(int16 index, int16 value) { - WRITE_LE_UINT16(_gameState + index * 2, value); -} - -int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { +int16 *GameDatabaseV2::findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { Object *obj = getObject(objectIndex); int16 *prop = (int16*)obj->getData(); @@ -430,14 +453,11 @@ int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, // Now check in the object hierarchy of the given object int16 parentObjectIndex = obj->getClass(); if (parentObjectIndex == 0) { - //debug(2, "! NULL(np)\n"); return NULL; } while (parentObjectIndex != 0) { - //debug(2, "parentObjectIndex = %04X\n", parentObjectIndex); - obj = getObject(parentObjectIndex); prop = (int16*)obj->getData(); @@ -469,12 +489,116 @@ int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, } - //debug(2, "! NULL(nf)\n"); + debug(1, "findObjectProperty(%04X, %04X) Property not found", objectIndex, propertyId); return NULL; } -int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { +const char *GameDatabaseV2::getString(uint16 offset) { + return (const char*)&_gameText[offset * 4]; +} + + +/* GameDatabaseV3 */ + +GameDatabaseV3::GameDatabaseV3(MadeEngine *vm) : GameDatabase(vm) { +} + +void GameDatabaseV3::load(Common::SeekableReadStream &sourceS) { + + // TODO: Read/verifiy header + + sourceS.seek(0x1E); + + uint32 objectIndexOffs = sourceS.readUint32LE(); + uint16 objectCount = sourceS.readUint16LE(); + uint32 gameStateOffs = sourceS.readUint32LE(); + _gameStateSize = sourceS.readUint32LE(); + uint32 objectsOffs = sourceS.readUint32LE(); + uint32 objectsSize = sourceS.readUint32LE(); + _mainCodeObjectIndex = sourceS.readUint16LE(); + + debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize); + + _gameState = new byte[_gameStateSize]; + sourceS.seek(gameStateOffs); + sourceS.read(_gameState, _gameStateSize); + + Common::Array<uint32> objectOffsets; + sourceS.seek(objectIndexOffs); + for (uint32 i = 0; i < objectCount; i++) + objectOffsets.push_back(sourceS.readUint32LE()); + + for (uint32 i = 0; i < objectCount; i++) { + Object *obj = new ObjectV3(); + + // The LSB indicates if it's a constant or variable object. + // Constant objects are loaded from disk, while variable objects exist + // in the _gameState buffer. + + if (objectOffsets[i] & 1) { + sourceS.seek(objectsOffs + objectOffsets[i] - 1); + obj->load(sourceS); + } else { + obj->load(_gameState + objectOffsets[i]); + } + _objects.push_back(obj); + } + +} + +bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String &description) { + Common::InSaveFile *in; + char desc[64]; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + return false; + } + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->read(desc, 64); + description = desc; + delete in; + return true; +} + +int16 GameDatabaseV3::savegame(const char *filename, const char *description, int16 version) { + Common::OutSaveFile *out; + char desc[64]; + int16 result = 0; + uint32 size = 4 + 4 + 2 + _gameStateSize; + if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { + warning("Can't create file '%s', game not saved", filename); + return 6; + } + strncpy(desc, description, 64); + out->writeUint32BE(MKID_BE('SGAM')); + out->writeUint32LE(size); + out->writeUint16LE(version); + out->write(desc, 64); + out->write(_gameState, _gameStateSize); + delete out; + return result; +} + +int16 GameDatabaseV3::loadgame(const char *filename, int16 version) { + Common::InSaveFile *in; + int16 result = 0; + //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + warning("Can't open file '%s', game not loaded", filename); + return 1; + } + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->skip(64); // skip savegame description + in->read(_gameState, _gameStateSize); + delete in; + return result; +} + +int16 *GameDatabaseV3::findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { Object *obj = getObject(objectIndex); int16 *prop = (int16*)obj->getData(); @@ -502,14 +626,11 @@ int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, // Now check in the object hierarchy of the given object int16 parentObjectIndex = obj->getClass(); if (parentObjectIndex == 0) { - //debug(2, "! NULL(np)\n"); return NULL; } while (parentObjectIndex != 0) { - //debug(2, "parentObjectIndex = %04X\n", parentObjectIndex); - obj = getObject(parentObjectIndex); prop = (int16*)obj->getData(); @@ -551,70 +672,13 @@ int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, } - //debug(2, "! NULL(nf)\n"); return NULL; - -} - -int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { - switch (_vm->_engineVersion) { - case 2: - return getObjectPropertyPtrV2(objectIndex, propertyId, propertyFlag); - case 3: - return getObjectPropertyPtrV3(objectIndex, propertyId, propertyFlag); - default: - error("GameDatabase::getObjectPropertyPtr() Unknown engine version"); - return NULL; - } -} - -int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) { - - if (objectIndex == 0) - return 0; - - int16 propertyFlag; - int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag); - if (property) { - return (int16)READ_LE_UINT16(property); - } else { - return 0; - } - } -int16 GameDatabase::setObjectProperty(int16 objectIndex, int16 propertyId, int16 value) { - - if (objectIndex == 0) - return 0; - - int16 propertyFlag; - int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag); - - if (property) { - if (propertyFlag == 1) { - WRITE_LE_UINT16(property, value); - } else { - debug(2, "GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n", - objectIndex, propertyId, value); - } - return value; - } else { - return 0; - } - -} - -const char *GameDatabase::getString(uint16 offset) { - return (const char*)&_gameText[offset * 4]; -} - -void GameDatabase::dumpObject(int16 index) { - Object *obj = getObject(index); - char fn[512]; - sprintf(fn, "obj%04X.0", index); - obj->dump(fn); +const char *GameDatabaseV3::getString(uint16 offset) { + // Not used in version 3 games + return NULL; } } // End of namespace Made diff --git a/engines/made/database.h b/engines/made/database.h index b92bd8f2dd..466d1a8f69 100644 --- a/engines/made/database.h +++ b/engines/made/database.h @@ -40,26 +40,25 @@ namespace Made { class Object { public: Object(); - ~Object(); - int loadVersion2(Common::SeekableReadStream &source); - int loadVersion3(Common::SeekableReadStream &source); - int loadVersion3(byte *source); + virtual ~Object(); + + virtual int load(Common::SeekableReadStream &source) = 0; + virtual int load(byte *source) = 0; + virtual int save(Common::WriteStream &dest) = 0; + virtual uint16 getFlags() = 0; + virtual uint16 getClass() = 0; + virtual uint16 getSize() = 0; + virtual byte getCount1() = 0; + virtual byte getCount2() = 0; + virtual byte *getData() = 0; + virtual bool isConstant() = 0; - uint16 getFlags() const; - uint16 getClass() const; - uint16 getSize() const; - - byte getCount1() const; - byte getCount2() const; - - byte *getData(); const char *getString(); void setString(const char *str); bool isObject(); bool isVector(); - bool isConstant() const { return !(getFlags() & 1); } - + int16 getVectorSize(); int16 getVectorItem(int16 index); void setVectorItem(int16 index, int16 value); @@ -72,52 +71,113 @@ protected: byte *_objData; }; +class ObjectV2 : public Object { +public: + int load(Common::SeekableReadStream &source); + int load(byte *source); + int save(Common::WriteStream &dest); + uint16 getFlags(); + uint16 getClass(); + uint16 getSize(); + byte getCount1(); + byte getCount2(); + byte *getData(); + + bool isConstant() { + return false; + } + +}; + +class ObjectV3 : public Object { +public: + int load(Common::SeekableReadStream &source); + int load(byte *source); + int save(Common::WriteStream &dest); + uint16 getFlags(); + uint16 getClass(); + uint16 getSize(); + byte getCount1(); + byte getCount2(); + byte *getData(); + + bool isConstant() { + return !(getFlags() & 1); + } + +}; + class GameDatabase { public: GameDatabase(MadeEngine *vm); - ~GameDatabase(); + virtual ~GameDatabase(); void open(const char *filename); void openFromRed(const char *redFilename, const char *filename); - bool getSavegameDescription(const char *filename, Common::String &description); - int16 savegame(const char *filename, const char *description, int16 version); - int16 loadgame(const char *filename, int16 version); - - Object *getObject(int16 index) const { + Object *getObject(int16 index) const { if (index >= 1) return _objects[index - 1]; else return NULL; } + uint getObjectCount() const { return _objects.size(); } + int16 getMainCodeObjectIndex() const { return _mainCodeObjectIndex; } int16 getVar(int16 index); void setVar(int16 index, int16 value); - - int16 *getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - int16 *getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - + + const char *getObjectString(int16 index); + void setObjectString(int16 index, const char *str); + + virtual int16 *findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) = 0; + virtual const char *getString(uint16 offset) = 0; + virtual bool getSavegameDescription(const char *filename, Common::String &description) = 0; + virtual int16 savegame(const char *filename, const char *description, int16 version) = 0; + virtual int16 loadgame(const char *filename, int16 version) = 0; + int16 getObjectProperty(int16 objectIndex, int16 propertyId); int16 setObjectProperty(int16 objectIndex, int16 propertyId, int16 value); - - const char *getString(uint16 offset); void dumpObject(int16 index); - + protected: MadeEngine *_vm; Common::Array<Object*> _objects; byte *_gameState; uint32 _gameStateSize; - char *_gameText; int16 _mainCodeObjectIndex; + virtual void load(Common::SeekableReadStream &sourceS) = 0; +}; + +class GameDatabaseV2 : public GameDatabase { +public: + GameDatabaseV2(MadeEngine *vm); + ~GameDatabaseV2(); + int16 *findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag); + const char *getString(uint16 offset); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); +protected: + char *_gameText; + void load(Common::SeekableReadStream &sourceS); +}; + +class GameDatabaseV3 : public GameDatabase { +public: + GameDatabaseV3(MadeEngine *vm); + int16 *findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag); + const char *getString(uint16 offset); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); +protected: + char *_gameText; void load(Common::SeekableReadStream &sourceS); - void loadVersion2(Common::SeekableReadStream &sourceS); - void loadVersion3(Common::SeekableReadStream &sourceS); }; } // End of namespace Made diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 6da3189163..dc7dbdee87 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -65,6 +65,7 @@ static const PlainGameDescriptor madeGames[] = { {"manhole", "The Manhole"}, {"rtz", "Return to Zork"}, {"lgop2", "Leather Goddesses of Phobos 2"}, + {"rodney", "Rodney's Fun Screen"}, {0, 0} }; @@ -74,9 +75,45 @@ namespace Made { static const MadeGameDescription gameDescriptions[] = { { - // Return to Zork - English CD version - // NOTE: This detects the game via the rtzcd.dat which is inside rtzcd.red. - // The entry below detects via rtzcd.red directly, which is the "official" way. + // NOTE: Return to Zork entries with *.dat are used to detect the game via rtzcd.dat, + // which is packed inside rtzcd.red. Entries with *.red refer to the packed file + // directly, which is the "official" way. + + // Return to Zork - English CD version 1.0 9/15/93 + // Patch #1953654 submitted by spookypeanut + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.dat", "e95c38ded389e39cfbf87a8cb250b12e"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD, + 0, + }, + + { + // Return to Zork - English CD version 1.0 9/15/93 + // Patch #1953654 submitted by spookypeanut + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.red", "cd8b62ece4677c438688c1de3f5379b9"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD_COMPRESSED, + 0, + }, + + { + // Return to Zork - English CD version 1.1 12/7/93 { "rtz", "CD", @@ -109,6 +146,23 @@ static const MadeGameDescription gameDescriptions[] = { { // Return to Zork - English CD version 1.2 9/29/94 + // Supplied by Dark-Star in the ScummVM forums + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD, + 0, + }, + + { + // Return to Zork - English CD version 1.2 9/29/94 { "rtz", "CD", @@ -123,6 +177,41 @@ static const MadeGameDescription gameDescriptions[] = { 0, }, + { + // Return to Zork - German CD version 1.2 9/29/94 + // (same as the English 1.2 version) + // Supplied by Dark-Star in the ScummVM forums + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD, + 0, + }, + + { + // Return to Zork - German CD version 1.2 4/18/95 + // (same as the English 1.2 version) + // Supplied by Dark-Star in the ScummVM forums + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD_COMPRESSED, + 0, + }, { // Return to Zork - English floppy version @@ -188,6 +277,22 @@ static const MadeGameDescription gameDescriptions[] = { 0, }, + { + // Rodney's Fun Screen + { + "rodney", + "", + AD_ENTRY1("rodneys.dat", "a79887dbaa47689facd7c6f09258ba5a"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RODNEY, + 0, + GF_FLOPPY, + 0, + }, + { AD_TABLE_END_MARKER, 0, 0, 0, 0 } }; @@ -240,7 +345,7 @@ public: } virtual const char *getCopyright() const { - return "MADE Engine"; + return "MADE Engine (C) Activision"; } virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; @@ -268,7 +373,8 @@ const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const FSList *fs Made::g_fallbackDesc.features = 0; Made::g_fallbackDesc.version = 0; - return (const Common::ADGameDescription *)&Made::g_fallbackDesc; + //return (const Common::ADGameDescription *)&Made::g_fallbackDesc; + return NULL; } #if PLUGIN_ENABLED_DYNAMIC(MADE) diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp index 081621ef18..ee702893a0 100644 --- a/engines/made/graphics.cpp +++ b/engines/made/graphics.cpp @@ -29,7 +29,24 @@ namespace Made { -void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame) { +byte ValueReader::readPixel() { + byte value; + if (_nibbleMode) { + if (_nibbleSwitch) { + value = (_buffer[0] >> 4) & 0x0F; + _buffer++; + } else { + value = _buffer[0] & 0x0F; + } + _nibbleSwitch = !_nibbleSwitch; + } else { + value = _buffer[0]; + _buffer++; + } + return value; +} + +void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, byte cmdFlags, byte pixelFlags, byte maskFlags, bool deltaFrame) { const int offsets[] = { 0, 1, 2, 3, @@ -43,11 +60,10 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u byte *cmdBuffer = source + cmdOffs; byte *maskBuffer = source + maskOffs; - byte *pixelBuffer = source + pixelOffs; + ValueReader pixelReader(source + pixelOffs, (pixelFlags & 2) != 0); byte *destPtr = (byte*)surface.getBasePtr(0, 0); - //byte lineBuf[320 * 4]; byte lineBuf[640 * 4]; byte bitBuf[40]; @@ -85,14 +101,14 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u switch (cmd) { case 0: - pixels[0] = *pixelBuffer++; + pixels[0] = pixelReader.readPixel(); for (int i = 0; i < 16; i++) lineBuf[drawDestOfs + offsets[i]] = pixels[0]; break; case 1: - pixels[0] = *pixelBuffer++; - pixels[1] = *pixelBuffer++; + pixels[0] = pixelReader.readPixel(); + pixels[1] = pixelReader.readPixel(); mask = READ_LE_UINT16(maskBuffer); maskBuffer += 2; for (int i = 0; i < 16; i++) { @@ -102,10 +118,10 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u break; case 2: - pixels[0] = *pixelBuffer++; - pixels[1] = *pixelBuffer++; - pixels[2] = *pixelBuffer++; - pixels[3] = *pixelBuffer++; + pixels[0] = pixelReader.readPixel(); + pixels[1] = pixelReader.readPixel(); + pixels[2] = pixelReader.readPixel(); + pixels[3] = pixelReader.readPixel(); mask = READ_LE_UINT32(maskBuffer); maskBuffer += 4; for (int i = 0; i < 16; i++) { @@ -149,4 +165,112 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u } +void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize) { + + uint16 width = surface.w; + uint16 height = surface.h; + uint16 bx = 0, by = 0, bw = ((width + 3) / 4) * 4; + + byte *cmdBuffer = source + cmdOffs; + byte *maskBuffer = source + maskOffs; + byte *pixelBuffer = source + pixelOffs; + + byte *destPtr = (byte*)surface.getBasePtr(0, 0); + + byte bitBuf[40]; + + int bitBufLastOfs = (((lineSize + 1) >> 1) << 1) - 2; + int bitBufLastCount = ((width + 3) >> 2) & 7; + if (bitBufLastCount == 0) + bitBufLastCount = 8; + + debug(1, "width = %d; bw = %d", width, bw); + + while (height > 0) { + + memcpy(bitBuf, cmdBuffer, lineSize); + cmdBuffer += lineSize; + + for (uint16 bitBufOfs = 0; bitBufOfs < lineSize; bitBufOfs += 2) { + + uint16 bits = READ_LE_UINT16(&bitBuf[bitBufOfs]); + + int bitCount; + if (bitBufOfs == bitBufLastOfs) + bitCount = bitBufLastCount; + else + bitCount = 8; + + for (int curCmd = 0; curCmd < bitCount; curCmd++) { + uint cmd = bits & 3; + bits >>= 2; + + byte pixels[4], block[16]; + uint32 mask; + + switch (cmd) { + + case 0: + pixels[0] = *pixelBuffer++; + for (int i = 0; i < 16; i++) + block[i] = pixels[0]; + break; + + case 1: + pixels[0] = *pixelBuffer++; + pixels[1] = *pixelBuffer++; + mask = READ_LE_UINT16(maskBuffer); + maskBuffer += 2; + for (int i = 0; i < 16; i++) { + block[i] = pixels[mask & 1]; + mask >>= 1; + } + break; + + case 2: + pixels[0] = *pixelBuffer++; + pixels[1] = *pixelBuffer++; + pixels[2] = *pixelBuffer++; + pixels[3] = *pixelBuffer++; + mask = READ_LE_UINT32(maskBuffer); + maskBuffer += 4; + for (int i = 0; i < 16; i++) { + block[i] = pixels[mask & 3]; + mask >>= 2; + } + break; + + case 3: + break; + + } + + if (cmd != 3) { + uint16 blockPos = 0; + uint32 maxW = MIN(4, surface.w - bx); + uint32 maxH = (MIN(4, surface.h - by) + by) * width; + for (uint32 yc = by * width; yc < maxH; yc += width) { + for (uint32 xc = 0; xc < maxW; xc++) { + destPtr[(bx + xc) + yc] = block[xc + blockPos]; + } + blockPos += 4; + } + } + + bx += 4; + if (bx >= bw) { + bx = 0; + by += 4; + } + + } + + } + + height -= 4; + + } + +} + } // End of namespace Made diff --git a/engines/made/graphics.h b/engines/made/graphics.h index 3c56bb4231..1a5cf72677 100644 --- a/engines/made/graphics.h +++ b/engines/made/graphics.h @@ -33,7 +33,18 @@ namespace Made { -void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame = false); +class ValueReader { +public: + ValueReader(byte *source, bool nibbleMode) : _buffer(source), _nibbleBuf(0), _nibbleMode(nibbleMode), _nibbleSwitch(false) {} + byte readPixel(); +protected: + byte _nibbleBuf; + bool _nibbleMode, _nibbleSwitch; + byte *_buffer; +}; + +void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, byte cmdFlags, byte pixelFlags, byte maskFlags, bool deltaFrame = false); +void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize); } // End of namespace Made diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 932f5ddcc4..59ec487c37 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -35,6 +35,7 @@ #include "base/plugins.h" #include "base/version.h" +#include "sound/audiocd.h" #include "sound/mixer.h" #include "made/made.h" @@ -86,7 +87,15 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _pmvPlayer = new PmvPlayer(this, _mixer); _res = new ProjectReader(); _screen = new Screen(this); - _dat = new GameDatabase(this); + + if (getGameID() == GID_LGOP2 || getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) { + _dat = new GameDatabaseV2(this); + } else if (getGameID() == GID_RTZ) { + _dat = new GameDatabaseV3(this); + } else { + error("Unknown GameID"); + } + _script = new ScriptInterpreter(this); int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); @@ -107,7 +116,15 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng debug(1, "Music disabled."); } - _soundRate = 8000; + _quit = false; + + // Set default sound frequency + // Return to Zork sets it itself via a script funtion + if (getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) { + _soundRate = 11025; + } else { + _soundRate = 8000; + } } @@ -132,21 +149,26 @@ int MadeEngine::init() { } int16 MadeEngine::getTimer(int16 timerNum) { - return (_system->getMillis() - _timers[timerNum]) / 60; + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers) && _timers[timerNum - 1] != -1) + return (_system->getMillis() - _timers[timerNum - 1]) / kTimerResolution; + else + return 32000; } void MadeEngine::setTimer(int16 timerNum, int16 value) { - _timers[timerNum] = value * 60; + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers)) + _timers[timerNum - 1] = value * kTimerResolution; } void MadeEngine::resetTimer(int16 timerNum) { - _timers[timerNum] = _system->getMillis(); + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers)) + _timers[timerNum - 1] = _system->getMillis(); } int16 MadeEngine::allocTimer() { for (int i = 0; i < ARRAYSIZE(_timers); i++) { if (_timers[i] == -1) { - resetTimer(i); + _timers[i] = _system->getMillis(); return i + 1; } } @@ -154,14 +176,79 @@ int16 MadeEngine::allocTimer() { } void MadeEngine::freeTimer(int16 timerNum) { - _timers[timerNum] = -1; + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers)) + _timers[timerNum - 1] = -1; +} + +Common::String MadeEngine::getSavegameFilename(int16 saveNum) { + char filename[256]; + snprintf(filename, 256, "%s.%03d", getTargetName().c_str(), saveNum); + return filename; +} + +void MadeEngine::handleEvents() { + + Common::Event event; + Common::EventManager *eventMan = _system->getEventManager(); + + // NOTE: Don't reset _eventNum to 0 here or no events will get through to the scripts. + + while (eventMan->pollEvent(event)) { + switch (event.type) { + + case Common::EVENT_MOUSEMOVE: + _eventMouseX = event.mouse.x; + _eventMouseY = event.mouse.y; + break; + + case Common::EVENT_LBUTTONDOWN: + _eventNum = 1; + break; + + /* + case Common::EVENT_LBUTTONUP: + _eventNum = 2; // TODO: Is this correct? + break; + */ + + case Common::EVENT_RBUTTONDOWN: + _eventNum = 3; + break; + + /* + case Common::EVENT_RBUTTONUP: + eventNum = 4; // TODO: Is this correct? + break; + */ + + case Common::EVENT_KEYDOWN: + _eventKey = event.kbd.ascii; + // For unknown reasons, the game accepts ASCII code + // 9 as backspace + if (_eventKey == Common::KEYCODE_BACKSPACE) + _eventKey = 9; + _eventNum = 5; + break; + + case Common::EVENT_QUIT: + _quit = true; + break; + + default: + break; + + } + } + + AudioCD.updateCD(); + } int MadeEngine::go() { for (int i = 0; i < ARRAYSIZE(_timers); i++) _timers[i] = -1; - + if (getGameID() == GID_RTZ) { _engineVersion = 3; if (getFeatures() & GF_DEMO) { @@ -187,12 +274,28 @@ int MadeEngine::go() { _engineVersion = 2; _dat->open("lgop2.dat"); _res->open("lgop2.prj"); + } else if (getGameID() == GID_RODNEY) { + _engineVersion = 2; + _dat->open("rodneys.dat"); + _res->open("rodneys.prj"); } else { error ("Unknown MADE game"); } - _eventMouseX = _eventMouseY = 0; + // FIXME: This should make things a little faster until proper dirty rectangles + // are implemented. + // NOTE: Disabled again since it causes major graphics errors. + //_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true); + + _autoStopSound = false; + _eventNum = _eventKey = _eventMouseX = _eventMouseY = 0; + +#ifdef DUMP_SCRIPTS + _script->dumpAllScripts(); +#else + _screen->setDefaultMouseCursor(); _script->runScript(_dat->getMainCodeObjectIndex()); +#endif return 0; } diff --git a/engines/made/made.h b/engines/made/made.h index b3a25b4e02..461941e5cf 100644 --- a/engines/made/made.h +++ b/engines/made/made.h @@ -48,18 +48,21 @@ namespace Made { enum MadeGameID { - GID_RTZ = 0, - GID_MANHOLE = 1, - GID_LGOP2 = 2 + GID_RTZ = 0, + GID_MANHOLE = 1, + GID_LGOP2 = 2, + GID_RODNEY = 3 }; enum MadeGameFeatures { - GF_DEMO = 1 << 0, - GF_CD = 1 << 1, - GF_CD_COMPRESSED = 1 << 2, - GF_FLOPPY = 1 << 3 + GF_DEMO = 1 << 0, + GF_CD = 1 << 1, + GF_CD_COMPRESSED = 1 << 2, + GF_FLOPPY = 1 << 3 }; +const uint32 kTimerResolution = 40; + struct MadeGameDescription; class ProjectReader; @@ -91,7 +94,6 @@ public: uint32 getFeatures() const; uint16 getVersion() const; Common::Platform getPlatform() const; - void update_events(); private: public: @@ -102,9 +104,15 @@ public: ScriptInterpreter *_script; MusicPlayer *_music; + bool _quit; + + uint16 _eventNum; int _eventMouseX, _eventMouseY; uint16 _eventKey; + int _soundRate; + bool _autoStopSound; + int _musicVolume; // 2 = LGOP2, Manhole N&E @@ -118,6 +126,11 @@ public: int16 allocTimer(); void freeTimer(int16 timerNum); + const Common::String getTargetName() { return _targetName; } + Common::String getSavegameFilename(int16 saveNum); + + void handleEvents(); + }; } // End of namespace Made diff --git a/engines/made/module.mk b/engines/made/module.mk index 164e1bfba4..b3d004aa4c 100644 --- a/engines/made/module.mk +++ b/engines/made/module.mk @@ -10,10 +10,9 @@ MODULE_OBJS = \ redreader.o \ resource.o \ screen.o \ + screenfx.o \ script.o \ - scriptfuncs_lgop2.o \ - scriptfuncs_mhne.o \ - scriptfuncs_rtz.o \ + scriptfuncs.o \ sound.o diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 06dc4e5aed..1a8ca9c50a 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -48,14 +48,17 @@ void PmvPlayer::play(const char *filename) { readChunk(chunkType, chunkSize); // "MHED" // TODO: Evaluate header - //_fd->skip(0x3A); uint frameDelay = _fd->readUint16LE(); _fd->skip(10); uint soundFreq = _fd->readUint16LE(); - // FIXME: weird frequencies... (11127 or 22254) - //if (soundFreq == 11127) soundFreq = 11025; - //if (soundFreq == 22254) soundFreq = 22050; + // Note: There seem to be weird sound frequencies in PMV videos. + // Not sure why, but leaving those original frequencies intact + // results to sound being choppy. Therefore, we set them to more + // "common" values here (11025 instead of 11127 and 22050 instead + // of 22254) + if (soundFreq == 11127) soundFreq = 11025; + if (soundFreq == 22254) soundFreq = 22050; int unk; @@ -74,10 +77,12 @@ void PmvPlayer::play(const char *filename) { uint32 frameCount = 0; uint16 chunkCount = 0; uint32 soundSize = 0; - uint32 palChunkOfs = 0; + uint32 soundChunkOfs = 0, palChunkOfs = 0; uint32 palSize = 0; byte *frameData, *audioData, *soundData, *palData, *imageData; bool firstTime = true; + + uint32 soundStartTime = 0, skipFrames = 0; uint32 frameNum; uint16 width, height, cmdOffs, pixelOffs, maskOffs, lineSize; @@ -89,6 +94,8 @@ void PmvPlayer::play(const char *filename) { while (!_abort && !_fd->eof()) { + int32 frameTime = _vm->_system->getMillis(); + readChunk(chunkType, chunkSize); if (_fd->eof()) @@ -96,27 +103,34 @@ void PmvPlayer::play(const char *filename) { frameData = new byte[chunkSize]; _fd->read(frameData, chunkSize); + + soundChunkOfs = READ_LE_UINT32(frameData + 8); + palChunkOfs = READ_LE_UINT32(frameData + 16); // Handle audio - audioData = frameData + READ_LE_UINT32(frameData + 8) - 8; - chunkSize = READ_LE_UINT16(audioData + 4); - chunkCount = READ_LE_UINT16(audioData + 6); + if (soundChunkOfs) { + + audioData = frameData + soundChunkOfs - 8; + chunkSize = READ_LE_UINT16(audioData + 4); + chunkCount = READ_LE_UINT16(audioData + 6); - if (chunkCount > 50) break; // FIXME: this is a hack + debug(1, "chunkCount = %d; chunkSize = %d; total = %d\n", chunkCount, chunkSize, chunkCount * chunkSize); - debug(2, "chunkCount = %d; chunkSize = %d\n", chunkCount, chunkSize); + if (chunkCount > 50) break; // FIXME: this is a hack - soundSize = chunkCount * chunkSize; - soundData = new byte[soundSize]; - decompressSound(audioData + 8, soundData, chunkSize, chunkCount); - _audioStream->queueBuffer(soundData, soundSize); + soundSize = chunkCount * chunkSize; + soundData = new byte[soundSize]; + decompressSound(audioData + 8, soundData, chunkSize, chunkCount); + _audioStream->queueBuffer(soundData, soundSize); + + } // Handle palette - palChunkOfs = READ_LE_UINT32(frameData + 16); if (palChunkOfs) { palData = frameData + palChunkOfs - 8; palSize = READ_LE_UINT32(palData + 4); decompressPalette(palData + 8, _paletteRGB, palSize); + _vm->_screen->setRGBPalette(_paletteRGB); } // Handle video @@ -138,24 +152,34 @@ void PmvPlayer::play(const char *filename) { _surface->create(width, height, 1); } - decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0); + decompressMovieImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize); if (firstTime) { _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream); + soundStartTime = g_system->getMillis(); + skipFrames = 0; firstTime = false; } - _vm->_screen->setRGBPalette(_paletteRGB); handleEvents(); updateScreen(); - frameCount++; - delete[] frameData; - while (_mixer->getSoundElapsedTime(_audioStreamHandle) < frameCount * frameDelay) { - _vm->_system->delayMillis(10); - } + if (skipFrames == 0) { + int32 waitTime = (frameCount * frameDelay) - + (g_system->getMillis() - soundStartTime) - (_vm->_system->getMillis() - frameTime); + + if (waitTime < 0) { + skipFrames = -waitTime / frameDelay; + warning("Video A/V sync broken, skipping %d frame(s)", skipFrames + 1); + } else if (waitTime > 0) + g_system->delayMillis(waitTime); + + } else + skipFrames--; + + frameCount++; } @@ -188,8 +212,8 @@ void PmvPlayer::handleEvents() { _abort = true; break; case Common::EVENT_QUIT: - // TODO: Exit more gracefully - g_system->quit(); + _vm->_quit = true; + _abort = true; break; default: break; diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index 7151f2424a..2cae8b276c 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -59,9 +59,9 @@ void PictureResource::load(byte *source, int size) { Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); _hasPalette = (sourceS->readByte() != 0); - sourceS->readByte(); - sourceS->readByte(); - sourceS->readByte(); + byte cmdFlags = sourceS->readByte(); + byte pixelFlags = sourceS->readByte(); + byte maskFlags = sourceS->readByte(); uint16 cmdOffs = sourceS->readUint16LE(); uint16 pixelOffs = sourceS->readUint16LE(); uint16 maskOffs = sourceS->readUint16LE(); @@ -69,7 +69,11 @@ void PictureResource::load(byte *source, int size) { /*uint16 u = */sourceS->readUint16LE(); uint16 width = sourceS->readUint16LE(); uint16 height = sourceS->readUint16LE(); - + + if (cmdFlags || pixelFlags || maskFlags) { + warning("PictureResource::load() Graphic has flags set"); + } + _paletteColorCount = (cmdOffs - 18) / 3; // 18 = sizeof header debug(2, "width = %d; height = %d\n", width, height); @@ -82,7 +86,7 @@ void PictureResource::load(byte *source, int size) { _picture = new Graphics::Surface(); _picture->create(width, height, 1); - decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize); + decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags); delete sourceS; @@ -94,7 +98,8 @@ AnimationResource::AnimationResource() { } AnimationResource::~AnimationResource() { - // TODO: Free anim frames + for (uint i = 0; i < _frames.size(); i++) + delete _frames[i]; } void AnimationResource::load(byte *source, int size) { @@ -136,7 +141,7 @@ void AnimationResource::load(byte *source, int size) { Graphics::Surface *frame = new Graphics::Surface(); frame->create(frameWidth, frameHeight, 1); - decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, _flags & 1); + decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, 0, 0, 0, _flags & 1); _frames.push_back(frame); @@ -372,7 +377,7 @@ bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size if (slot && slot->size > 0) { size = slot->size - 62; buffer = new byte[size]; - debug(2, "ProjectReader::loadResource() %08X\n", slot->offs + 62); fflush(stdout); + debug(2, "ProjectReader::loadResource() %08X", slot->offs + 62); _fd->seek(slot->offs + 62); _fd->read(buffer, size); return true; @@ -384,8 +389,7 @@ bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size ResourceSlot *ProjectReader::getResourceSlot(uint32 resType, uint index) { ResourceSlots *slots = _resSlots[resType]; if (index >= 1 && index < slots->size()) { - ResourceSlot *slot = &slots->operator[](index); - return slot; + return &slots->operator[](index); } else { return NULL; } @@ -398,22 +402,20 @@ Resource *ProjectReader::getResourceFromCache(ResourceSlot *slot) { } void ProjectReader::addResourceToCache(ResourceSlot *slot, Resource *res) { - if (_cacheCount >= kMaxResourceCacheCount) { + if (_cacheCount >= kMaxResourceCacheCount) purgeCache(); - } slot->res = res; - slot->refCount = 0; + slot->refCount = 1; _cacheCount++; } void ProjectReader::tossResourceFromCache(ResourceSlot *slot) { - if (slot->res) { + if (slot->res) slot->refCount--; - } } void ProjectReader::purgeCache() { - printf("ProjectReader::purgeCache()\n"); + debug(2, "ProjectReader::purgeCache()"); for (ResMap::const_iterator resTypeIter = _resSlots.begin(); resTypeIter != _resSlots.end(); ++resTypeIter) { ResourceSlots *slots = (*resTypeIter)._value; for (ResourceSlots::iterator slotIter = slots->begin(); slotIter != slots->end(); ++slotIter) { diff --git a/engines/made/resource.h b/engines/made/resource.h index be85561318..cb6e0b65f4 100644 --- a/engines/made/resource.h +++ b/engines/made/resource.h @@ -35,7 +35,7 @@ namespace Made { -const int kMaxResourceCacheCount = 200; +const int kMaxResourceCacheCount = 100; enum ResourceType { kResARCH = MKID_BE('ARCH'), @@ -81,7 +81,14 @@ public: ~AnimationResource(); void load(byte *source, int size); int getCount() const { return _frames.size(); } - Graphics::Surface *getFrame(int index) const { return _frames[index]; } + Graphics::Surface *getFrame(int index) const { + if ((uint)index < _frames.size()) { + return _frames[index]; + } else { + warning("getFrame: Tried to obtain invalid frame %i, array has %i frames", index, _frames.size()); + return _frames[_frames.size() - 1]; + } + } uint16 getFlags() const { return _flags; } int16 getWidth() const { return _width; } int16 getHeight() const { return _height; } diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index 74053e70a2..cecd0c8968 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -32,20 +32,27 @@ namespace Made { Screen::Screen(MadeEngine *vm) : _vm(vm) { - _screen1 = new Graphics::Surface(); - _screen1->create(320, 200, 1); - _screen2 = new Graphics::Surface(); - _screen2->create(320, 200, 1); - - _clipInfo1.x = _clipInfo2.x = 0; - _clipInfo1.y = _clipInfo2.y = 0; - _clipInfo1.w = _clipInfo2.w = 320; - _clipInfo1.h = _clipInfo2.h = 200; - - _clipInfo1.destSurface = _screen1; - _clipInfo2.destSurface = _screen2; - _clipArea.destSurface = _screen2; - + _backgroundScreen = new Graphics::Surface(); + _backgroundScreen->create(320, 200, 1); + + _workScreen = new Graphics::Surface(); + _workScreen->create(320, 200, 1); + + _backgroundScreenDrawCtx.clipRect = Common::Rect(320, 200); + _workScreenDrawCtx.clipRect = Common::Rect(320, 200); + + _backgroundScreenDrawCtx.destSurface = _backgroundScreen; + _workScreenDrawCtx.destSurface = _workScreen; + _clipArea.destSurface = _workScreen; + + // Screen mask is only needed in v2 games + if (_vm->getGameID() != GID_RTZ) { + _screenMask = new Graphics::Surface(); + _screenMask->create(320, 200, 1); + _maskDrawCtx.clipRect = Common::Rect(320, 200); + _maskDrawCtx.destSurface = _screenMask; + } + for (int i = 0; i <= 3; i++) _excludeClipAreaEnabled[i] = false; @@ -62,8 +69,10 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _ground = 1; _clip = 0; _exclude = 0; + _mask = 0; _visualEffectNum = 0; + _fx = new ScreenEffects(this); _textX = 0; _textY = 0; @@ -74,64 +83,130 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _textRect.bottom = 200; _font = NULL; _currentFontNum = 0; - _fontDrawCtx.x = 0; - _fontDrawCtx.y = 0; - _fontDrawCtx.w = 320; - _fontDrawCtx.h = 200; - _fontDrawCtx.destSurface = _screen1; + _fontDrawCtx.clipRect = Common::Rect(320, 200); + _fontDrawCtx.destSurface = _backgroundScreen; clearChannels(); } Screen::~Screen() { - delete _screen1; - delete _screen2; + delete _backgroundScreen; + delete _workScreen; + if (_vm->getGameID() != GID_RTZ) + delete _screenMask; + delete _fx; } void Screen::clearScreen() { - _screen1->fillRect(Common::Rect(0, 0, 320, 200), 0); - _screen2->fillRect(Common::Rect(0, 0, 320, 200), 0); + _backgroundScreen->fillRect(Common::Rect(0, 0, 320, 200), 0); + _workScreen->fillRect(Common::Rect(0, 0, 320, 200), 0); + if (_vm->getGameID() != GID_RTZ) + _screenMask->fillRect(Common::Rect(0, 0, 320, 200), 0); + _mask = 0; _needPalette = true; } -void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo) { +void Screen::setExcludeArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { + + _excludeClipAreaEnabled[0] = false; + _excludeClipAreaEnabled[1] = false; + _excludeClipAreaEnabled[2] = false; + _excludeClipAreaEnabled[3] = false; + + if (x1 == 0 && y1 == 0 && x2 == 0 && y2 == 0) { + _excludeClipArea[0].clipRect = Common::Rect(320, 200); + _excludeClipAreaEnabled[0] = true; + return; + } + + if (y1 > 0 && y2 > 0) { + _excludeClipArea[0].clipRect = Common::Rect(320, y1); + _excludeClipAreaEnabled[0] = true; + } + + if (y1 < 200 && y2 < 200) { + _excludeClipArea[1].clipRect = Common::Rect(0, y2, 320, 200); + _excludeClipAreaEnabled[1] = true; + } + + if (x1 > 0 && x2 > 0) { + _excludeClipArea[2].clipRect = Common::Rect(0, y1, x1, y2); + _excludeClipAreaEnabled[2] = true; + } + + if (x1 < 320 && x2 < 320) { + _excludeClipArea[3].clipRect = Common::Rect(x2, y1, 320, y2); + _excludeClipAreaEnabled[3] = true; + } + +} + +void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo) { - byte *source, *dest; + byte *source, *dest, *maskp = 0; int startX = 0; int startY = 0; int clipWidth = sourceSurface->w; int clipHeight = sourceSurface->h; - if (x < 0) { - startX = -x; + if (x < clipInfo.clipRect.left) { + startX = clipInfo.clipRect.left - x; clipWidth -= startX; - x = 0; + x = clipInfo.clipRect.left; } - if (y < 0) { - startY = -y; + if (y < clipInfo.clipRect.top) { + startY = clipInfo.clipRect.top - y; clipHeight -= startY; - y = 0; + y = clipInfo.clipRect.top; } - if (x + clipWidth > clipInfo.x + clipInfo.w) { - clipWidth = clipInfo.x + clipInfo.w - x; + if (x + clipWidth > clipInfo.clipRect.right) { + clipWidth = clipInfo.clipRect.right - x; } - if (y + clipHeight > clipInfo.y + clipInfo.h) { - clipHeight = clipInfo.y + clipInfo.h - y; + if (y + clipHeight > clipInfo.clipRect.bottom) { + clipHeight = clipInfo.clipRect.bottom - y; } source = (byte*)sourceSurface->getBasePtr(startX, startY); dest = (byte*)clipInfo.destSurface->getBasePtr(x, y); + if (_vm->getGameID() != GID_RTZ) + maskp = (byte*)_maskDrawCtx.destSurface->getBasePtr(x, y); + + int32 sourcePitch, linePtrAdd; + byte *linePtr; + + if (flipX) { + linePtrAdd = -1; + } else { + linePtrAdd = 1; + } + + if (flipY) { + sourcePitch = -sourceSurface->pitch; + source += (clipHeight - 1) * sourceSurface->pitch; + } else { + sourcePitch = sourceSurface->pitch; + } for (int16 yc = 0; yc < clipHeight; yc++) { + if (flipX) { + linePtr = source + sourceSurface->w; + } else { + linePtr = source; + } for (int16 xc = 0; xc < clipWidth; xc++) { - if (source[xc]) - dest[xc] = source[xc]; + if (*linePtr && (_vm->getGameID() == GID_RTZ || (mask == 0 || maskp[xc] == 0))) { + if (*linePtr) + dest[xc] = *linePtr; + } + linePtr += linePtrAdd; } - source += sourceSurface->pitch; + source += sourcePitch; dest += clipInfo.destSurface->pitch; + if (_vm->getGameID() != GID_RTZ) + maskp += _maskDrawCtx.destSurface->pitch; } } @@ -191,11 +266,16 @@ uint16 Screen::setChannelLocation(uint16 channelIndex, int16 x, int16 y) { uint16 Screen::setChannelContent(uint16 channelIndex, uint16 index) { if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0) return 0; - //debug(2, "setChannelContent(%d, %04X)\n", channelIndex, index); fflush(stdout); g_system->delayMillis(5000); _channels[channelIndex - 1].index = index; return updateChannel(channelIndex - 1) + 1; } +void Screen::setChannelUseMask(uint16 channelIndex) { + if (channelIndex < 1 || channelIndex >= 100) + return; + _channels[channelIndex - 1].mask = _mask; +} + void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask) { for (int i = 0; i <= 3; i++) @@ -208,8 +288,8 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask debug(2, "drawSpriteChannels() i = %d\n", i); if (((_channels[i].state & includeStateMask) == includeStateMask) && (_channels[i].state & excludeStateMask) == 0) { - uint16 flag1 = _channels[i].state & 0x10; - uint16 flag2 = _channels[i].state & 0x20; + int16 flipX = _channels[i].state & 0x10; + int16 flipY = _channels[i].state & 0x20; debug(2, "drawSpriteChannels() type = %d; index = %04X\n", _channels[i].type, _channels[i].index); @@ -217,38 +297,38 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask case 1: // drawFlex if (_channels[i].state & 4) { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _clipArea); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, _clipArea); } else if (_channels[i].state & 8) { for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) { if (_excludeClipAreaEnabled[excludeIndex]) { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _excludeClipArea[excludeIndex]); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, _excludeClipArea[excludeIndex]); } } } else { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, clipInfo); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, clipInfo); } break; - + case 2: // drawObjectText printObjectText(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].fontNum, _channels[i].textColor, _channels[i].outlineColor, clipInfo); break; case 3: // drawAnimFrame if (_channels[i].state & 4) { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _clipArea); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, _clipArea); } else if (_channels[i].state & 8) { for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) { if (_excludeClipAreaEnabled[excludeIndex]) { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _excludeClipArea[excludeIndex]); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, _excludeClipArea[excludeIndex]); } } } else { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, clipInfo); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, clipInfo); } break; case 4: // drawMenuText - // TODO + // Never used in any game break; default: @@ -265,12 +345,14 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask void Screen::updateSprites() { // TODO: This needs some more work, dirty rectangles are currently not used - memcpy(_screen2->pixels, _screen1->pixels, 64000); + memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); - drawSpriteChannels(_clipInfo1, 3, 0); - drawSpriteChannels(_clipInfo2, 1, 2); + drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); + drawSpriteChannels(_workScreenDrawCtx, 1, 2); - _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h); + _vm->_system->copyRectToScreen((const byte*)_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); + + _vm->_system->updateScreen(); } @@ -278,11 +360,12 @@ void Screen::clearChannels() { for (uint16 i = 0; i < ARRAYSIZE(_channels); i++) { _channels[i].type = 0; _channels[i].index = 0; + _channels[i].mask = 0; } _channelsUsedCount = 0; } -uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) { +uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo) { if (flexIndex == 0) return 0; @@ -290,7 +373,7 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 PictureResource *flex = _vm->_res->getPicture(flexIndex); Graphics::Surface *sourceSurface = flex->getPicture(); - drawSurface(sourceSurface, x, y, clipInfo); + drawSurface(sourceSurface, x, y, flipX, flipY, mask, clipInfo); // Palette is set in showPage if (flex->hasPalette() && !_paletteLock && _needPalette) { @@ -307,7 +390,7 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 return 0; } -void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) { +void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY, const ClipInfo &clipInfo) { if (frameNum < 0) return; @@ -315,24 +398,29 @@ void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, u AnimationResource *anim = _vm->_res->getAnimation(animIndex); Graphics::Surface *sourceSurface = anim->getFrame(frameNum); - drawSurface(sourceSurface, x, y, clipInfo); + drawSurface(sourceSurface, x, y, flipX, flipY, 0, clipInfo); _vm->_res->freeResource(anim); } -uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) { - drawFlex(index, x, y, flag1, flag2, _clipInfo1); +uint16 Screen::drawPic(uint16 index, int16 x, int16 y, int16 flipX, int16 flipY) { + drawFlex(index, x, y, flipX, flipY, 0, _backgroundScreenDrawCtx); return 0; } -uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2) { - drawAnimFrame(animIndex, x, y, frameNum, flag1, flag2, _clipInfo1); +uint16 Screen::drawMask(uint16 index, int16 x, int16 y) { + drawFlex(index, x, y, 0, 0, 0, _maskDrawCtx); + return 0; +} + +uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY) { + drawAnimFrame(animIndex, x, y, frameNum, flipX, flipY, _backgroundScreenDrawCtx); return 0; } void Screen::addSprite(uint16 spriteIndex) { bool oldScreenLock = _screenLock; - drawFlex(spriteIndex, 0, 0, 0, 0, _clipInfo1); + drawFlex(spriteIndex, 0, 0, 0, 0, 0, _backgroundScreenDrawCtx); _screenLock = oldScreenLock; } @@ -342,7 +430,7 @@ uint16 Screen::drawSprite(uint16 flexIndex, int16 x, int16 y) { uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 y) { - debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); fflush(stdout); + debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); if (channelIndex < 1 || channelIndex >= 100) return 0; @@ -379,8 +467,8 @@ uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); - + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); + if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -432,7 +520,7 @@ uint16 Screen::placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -462,17 +550,6 @@ int16 Screen::getAnimFrame(uint16 channelIndex) { return _channels[channelIndex - 1].frameNum; } -int16 Screen::getAnimFrameCount(uint16 animIndex) { - int16 frameCount = 0; - AnimationResource *anim = _vm->_res->getAnimation(animIndex); - if (anim) { - frameCount = anim->getCount(); - _vm->_res->freeResource(anim); - } - return frameCount; -} - - uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor) { if (channelIndex < 1 || channelIndex >= 100 || textObjectIndex == 0 || fontNum == 0) @@ -525,7 +602,7 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -536,18 +613,17 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i void Screen::show() { // TODO - + if (_screenLock) return; - drawSpriteChannels(_clipInfo1, 3, 0); - memcpy(_screen2->pixels, _screen1->pixels, 64000); - drawSpriteChannels(_clipInfo2, 1, 2); + drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); + memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); + drawSpriteChannels(_workScreenDrawCtx, 1, 2); + + _fx->run(_visualEffectNum, _workScreen, _palette, _newPalette, _paletteColorCount); + _visualEffectNum = 0; - // TODO: Implement visual effects (palette fading etc.) - if (!_paletteLock) - setRGBPalette(_palette, 0, _paletteColorCount); - _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h); _vm->_system->updateScreen(); if (!_paletteInitialized) { @@ -559,19 +635,7 @@ void Screen::show() { } void Screen::flash(int flashCount) { - int palSize = _paletteColorCount * 3; - if (flashCount < 1) - flashCount = 1; - for (int i = 0; i < palSize; i++) - _fxPalette[i] = CLIP<byte>(255 - _palette[i], 0, 255); - while (flashCount--) { - setRGBPalette(_fxPalette, 0, _paletteColorCount); - _vm->_system->updateScreen(); - _vm->_system->delayMillis(30); - setRGBPalette(_palette, 0, _paletteColorCount); - _vm->_system->updateScreen(); - _vm->_system->delayMillis(30); - } + _fx->flash(flashCount, _palette, _paletteColorCount); } void Screen::setFont(int16 fontNum) { @@ -588,7 +652,7 @@ void Screen::printChar(uint c, int16 x, int16 y, byte color) { if (!_font) return; - int height = _font->getHeight(); + uint width = 8, height = _font->getHeight(); byte *charData = _font->getChar(c); if (!charData) @@ -596,10 +660,10 @@ void Screen::printChar(uint c, int16 x, int16 y, byte color) { byte p; byte *dest = (byte*)_fontDrawCtx.destSurface->getBasePtr(x, y); - - for (int16 yc = 0; yc < height; yc++) { + + for (uint yc = 0; yc < height; yc++) { p = charData[yc]; - for (int16 xc = 0; xc < 8; xc++) { + for (uint xc = 0; xc < width; xc++) { if (p & 0x80) dest[xc] = color; p <<= 1; @@ -690,7 +754,7 @@ void Screen::printText(const char *text) { } void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int16 textColor, int16 outlineColor, const ClipInfo &clipInfo) { - if (*text == 0 || x == 0 || y == 0) + if (*text == 0 || x < 0 || y < 0) return; int16 oldFontNum = _currentFontNum; @@ -728,5 +792,48 @@ int16 Screen::getTextWidth(int16 fontNum, const char *text) { return _font->getTextWidth(text); } +Graphics::Surface *Screen::lockScreen() { + return _vm->_system->lockScreen(); +} + +void Screen::unlockScreen() { + _vm->_system->unlockScreen(); +} + +void Screen::showWorkScreen() { + _vm->_system->copyRectToScreen((const byte*)_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); +} + +void Screen::updateScreenAndWait(int delay) { + _vm->_system->updateScreen(); + _vm->_system->delayMillis(delay); +} + +int16 Screen::addToSpriteList(int16 index, int16 xofs, int16 yofs) { + SpriteListItem item; + item.index = index; + item.xofs = xofs; + item.yofs = yofs; + _spriteList.push_back(item); + return _spriteList.size(); +} + +SpriteListItem Screen::getFromSpriteList(int16 index) { + if (((uint) index) > _spriteList.size()) { + SpriteListItem emptyItem; + emptyItem.index = 0; + return emptyItem; + } else { + return _spriteList[index - 1]; + } +} + +void Screen::clearSpriteList() { + _spriteList.clear(); +} + +void Screen::setDefaultMouseCursor() { + CursorMan.replaceCursor(defaultMouseCursor, 16, 16, 9, 2, 0); +} } // End of namespace Made diff --git a/engines/made/screen.h b/engines/made/screen.h index 0ca28086f9..5d55085e5c 100644 --- a/engines/made/screen.h +++ b/engines/made/screen.h @@ -28,10 +28,13 @@ #include "common/endian.h" #include "common/util.h" +#include "common/rect.h" #include "graphics/surface.h" +#include "graphics/cursorman.h" #include "made/resource.h" +#include "made/screenfx.h" namespace Made { @@ -46,15 +49,39 @@ struct SpriteChannel { uint16 fontNum; int16 textColor, outlineColor; int16 frameNum; + int16 mask; }; struct ClipInfo { - uint16 x, y, w, h; + Common::Rect clipRect; Graphics::Surface *destSurface; }; +struct SpriteListItem { + int16 index, xofs, yofs; +}; + class MadeEngine; +static const byte defaultMouseCursor[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 1, 1, 15, 1, 15, 1, 15, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 1, 15, 15, 1, 15, 1, 15, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 0, 1, 1, 1, 0, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 15, 15, 15, 1, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 1, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, + 1, 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 0, + 0, 1, 1, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + class Screen { public: Screen(MadeEngine *vm); @@ -62,16 +89,27 @@ public: void clearScreen(); - void drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo); + void drawSurface(Graphics::Surface *sourceSurface, int x, int y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo); + void loadRGBPalette(byte *palRGB, int count = 256); void setRGBPalette(byte *palRGB, int start = 0, int count = 256); bool isPaletteLocked() { return _paletteLock; } - void setScreenLock(bool lock) { _screenLock = lock; } void setPaletteLock(bool lock) { _paletteLock = lock; } + bool isScreenLocked() { return _screenLock; } + void setScreenLock(bool lock) { _screenLock = lock; } void setVisualEffectNum(int visualEffectNum) { _visualEffectNum = visualEffectNum; } - void setClip(uint16 clip) { _clip = clip; } - void setExclude(uint16 exclude) { _exclude = exclude; } - void setGround(uint16 ground) { _ground = ground; } + + void setClipArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { + _clipArea.clipRect = Common::Rect(x1, y1, x2, y2); + } + + void setExcludeArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2); + + void setClip(int16 clip) { _clip = clip; } + void setExclude(int16 exclude) { _exclude = exclude; } + void setGround(int16 ground) { _ground = ground; } + void setMask(int16 mask) { _mask = mask; } + void setTextColor(int16 color) { _textColor = color; } void setTextRect(const Common::Rect &textRect) { @@ -99,6 +137,11 @@ public: _textY = y; } + void homeText() { + _textX = _textRect.left; + _textY = _textRect.top; + } + uint16 updateChannel(uint16 channelIndex); void deleteChannel(uint16 channelIndex); int16 getChannelType(uint16 channelIndex); @@ -106,15 +149,19 @@ public: void setChannelState(uint16 channelIndex, int16 state); uint16 setChannelLocation(uint16 channelIndex, int16 x, int16 y); uint16 setChannelContent(uint16 channelIndex, uint16 index); + void setChannelUseMask(uint16 channelIndex); void drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask); void updateSprites(); void clearChannels(); - uint16 drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo); - void drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo); + uint16 drawFlex(uint16 flexIndex, int16 x, int16 y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo); + + void drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY, const ClipInfo &clipInfo); - uint16 drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2); - uint16 drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2); + uint16 drawPic(uint16 index, int16 x, int16 y, int16 flipX, int16 flipY); + uint16 drawMask(uint16 index, int16 x, int16 y); + + uint16 drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY); void addSprite(uint16 spriteIndex); @@ -124,14 +171,12 @@ public: uint16 placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y, int16 frameNum); int16 setAnimFrame(uint16 channelIndex, int16 frameNum); int16 getAnimFrame(uint16 channelIndex); - // TODO: Move to script function - int16 getAnimFrameCount(uint16 animIndex); uint16 placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor); void show(); void flash(int count); - + void setFont(int16 fontNum); void printChar(uint c, int16 x, int16 y, byte color); void printText(const char *text); @@ -139,15 +184,27 @@ public: void printObjectText(int16 objectIndex, int16 x, int16 y, int16 fontNum, int16 textColor, int16 outlineColor, const ClipInfo &clipInfo); int16 getTextWidth(int16 fontNum, const char *text); + // Interface functions for the screen effects class + Graphics::Surface *lockScreen(); + void unlockScreen(); + void showWorkScreen(); + void updateScreenAndWait(int delay); + + int16 addToSpriteList(int16 index, int16 xofs, int16 yofs); + SpriteListItem getFromSpriteList(int16 index); + void clearSpriteList(); + + void setDefaultMouseCursor(); protected: MadeEngine *_vm; + ScreenEffects *_fx; bool _screenLock; bool _paletteLock; byte _screenPalette[256 * 4]; - byte _palette[768], _newPalette[768], _fxPalette[768]; + byte _palette[768], _newPalette[768]; int _paletteColorCount, _oldPaletteColorCount; bool _paletteInitialized, _needPalette; int16 _textColor; @@ -160,17 +217,20 @@ protected: FontResource *_font; ClipInfo _fontDrawCtx; - uint16 _clip, _exclude, _ground; + int16 _clip, _exclude, _ground, _mask; int _visualEffectNum; - Graphics::Surface *_screen1, *_screen2; - ClipInfo _clipArea, _clipInfo1, _clipInfo2; + Graphics::Surface *_backgroundScreen, *_workScreen, *_screenMask; + ClipInfo _clipArea, _backgroundScreenDrawCtx, _workScreenDrawCtx, _maskDrawCtx; ClipInfo _excludeClipArea[4]; bool _excludeClipAreaEnabled[4]; uint16 _channelsUsedCount; SpriteChannel _channels[100]; + + Common::Array<SpriteListItem> _spriteList; + }; } // End of namespace Made diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp new file mode 100644 index 0000000000..ee96af601a --- /dev/null +++ b/engines/made/screenfx.cpp @@ -0,0 +1,356 @@ +/* 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 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 "made/made.h" +#include "made/screen.h" +#include "made/screenfx.h" + +namespace Made { + +const byte ScreenEffects::vfxOffsTable[64] = { + 5, 2, 6, 1, 4, 7, 3, 0, + 7, 4, 0, 3, 6, 1, 5, 2, + 2, 5, 1, 6, 3, 0, 4, 7, + 0, 3, 7, 4, 1, 6, 2, 5, + 4, 0, 2, 5, 7, 3, 1, 6, + 1, 6, 4, 0, 2, 5, 7, 3, + 6, 1, 3, 7, 5, 2, 0, 4, + 3, 7, 5, 2, 0, 4, 6, 1 +}; + +const byte ScreenEffects::vfxOffsIndexTable[8] = { + 6, 7, 2, 3, 4, 5, 0, 1 +}; + + +ScreenEffects::ScreenEffects(Screen *screen) : _screen(screen) { + vfxOffsTablePtr = &vfxOffsTable[6 * 8]; + vfxX1 = 0; + vfxY1 = 0; + vfxWidth = 0; + vfxHeight = 0; +} + +void ScreenEffects::run(int16 effectNum, Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + + // TODO: Put effect functions into an array + // TODO: Implement more visual effects + + switch (effectNum) { + + case 0: // No effect + vfx00(surface, palette, newPalette, colorCount); + break; + + case 2: + vfx02(surface, palette, newPalette, colorCount); + break; + + case 9: // "Checkerboard" effect + vfx09(surface, palette, newPalette, colorCount); + break; + + case 10: // "Screen wipe in", left to right + vfx10(surface, palette, newPalette, colorCount); + break; + + case 11: // "Screen wipe in", right to left + vfx11(surface, palette, newPalette, colorCount); + break; + + case 12: // "Screen wipe in", top to bottom + vfx12(surface, palette, newPalette, colorCount); + break; + + case 13: // "Screen wipe in", bottom to top + vfx13(surface, palette, newPalette, colorCount); + break; + + case 14: // "Screen open" effect + vfx14(surface, palette, newPalette, colorCount); + break; + + case 15: + vfx15(surface, palette, newPalette, colorCount); + break; + + case 17: // Palette fadeout/fadein + vfx17(surface, palette, newPalette, colorCount); + break; + + default: + vfx00(surface, palette, newPalette, colorCount); + warning("Unimplemented visual effect %d", effectNum); + + } + +} + +void ScreenEffects::flash(int flashCount, byte *palette, int colorCount) { + int palSize = colorCount * 3; + if (flashCount < 1) + flashCount = 1; + for (int i = 0; i < palSize; i++) + _fxPalette[i] = CLIP<byte>(255 - palette[i], 0, 255); + while (flashCount--) { + _screen->setRGBPalette(_fxPalette, 0, colorCount); + _screen->updateScreenAndWait(20); + _screen->setRGBPalette(palette, 0, colorCount); + _screen->updateScreenAndWait(20); + } +} + +void ScreenEffects::setPalette(byte *palette) { + if (!_screen->isPaletteLocked()) { + _screen->setRGBPalette(palette, 0, 256); + } +} + +void ScreenEffects::setBlendedPalette(byte *palette, byte *newPalette, int colorCount, int16 value, int16 maxValue) { + if (!_screen->isPaletteLocked()) { + int32 mulValue = (value * 64) / maxValue; + for (int i = 0; i < colorCount * 3; i++) + _fxPalette[i] = CLIP(newPalette[i] - (newPalette[i] - palette[i]) * mulValue / 64, 0, 255); + _screen->setRGBPalette(_fxPalette, 0, 256); + } +} + +void ScreenEffects::copyFxRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2) { + + // TODO: Clean up + + byte *src, *dst; + + x1 = CLIP<int16>(x1, 0, 320); + y1 = CLIP<int16>(y1, 0, 200); + x2 = CLIP<int16>(x2, 0, 320); + y2 = CLIP<int16>(y2, 0, 200); + + x2 -= x1; + y2 -= y1; + vfxX1 = x1 & 0x0E; + x1 += 16; + x1 = x1 & 0xFFF0; + x2 += vfxX1; + x2 -= 15; + if (x2 < 0) + x2 = 0; + vfxWidth = x2 & 0x0E; + x2 = x2 & 0xFFF0; + + vfxY1 = y1 & 7; + + byte *source = (byte*)surface->getBasePtr(x1, y1); + + Graphics::Surface *vgaScreen = _screen->lockScreen(); + byte *dest = (byte*)vgaScreen->getBasePtr(x1, y1); + + int16 addX = x2 / 16; + + while (y2-- > 0) { + + int16 addVal = vfxOffsTablePtr[vfxY1] * 2; + int16 w = 0; + vfxY1 = (vfxY1 + 1) & 7; + + src = source + addVal; + dst = dest + addVal; + + if (addVal < vfxX1) { + if (addVal < vfxWidth) + w = 1; + else + w = 0; + } else { + src -= 16; + dst -= 16; + if (addVal < vfxWidth) + w = 2; + else + w = 1; + } + + w += addX; + + while (w-- > 0) { + *dst++ = *src++; + *dst++ = *src++; + src += 14; + dst += 14; + } + + source += 320; + dest += 320; + + } + + vfxHeight = (vfxHeight + 1) & 7; + vfxOffsTablePtr = &vfxOffsTable[vfxOffsIndexTable[vfxHeight] * 8]; + + _screen->unlockScreen(); + +} + +void ScreenEffects::copyRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2) { + Graphics::Surface *vgaScreen = _screen->lockScreen(); + byte *source = (byte*)surface->getBasePtr(x1, y1); + byte *dest = (byte*)vgaScreen->getBasePtr(x1, y1); + for (int y = 0; y < y2 - y1; y++) { + memcpy(dest, source, x2 - x1); + dest += 320; + source += 320; + } + _screen->unlockScreen(); +} + +// No effect +void ScreenEffects::vfx00(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + setPalette(palette); + _screen->showWorkScreen(); + // FIXME: For Manhole; causes sluggish mouse + _screen->updateScreenAndWait(100); +} + +void ScreenEffects::vfx02(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int x = 312; x >= 0; x -= 8) { + copyRect(surface, x, 0, x + 8, 200); + setBlendedPalette(palette, newPalette, colorCount, 312 - x, 312); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Checkerboard" effect +void ScreenEffects::vfx09(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int i = 0; i < 8; i++) { + copyFxRect(surface, 0, 0, 320, 200); + for (int j = 0; j < 4; j++) { + setBlendedPalette(palette, newPalette, colorCount, i * 4 + j, 36/*FIX?*/); + _screen->updateScreenAndWait(25); + } + } + setPalette(palette); +} + +// "Screen wipe in", left to right +void ScreenEffects::vfx10(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int x = -56; x < 312; x += 8) { + copyFxRect(surface, x, 0, x + 64, 200); + setBlendedPalette(palette, newPalette, colorCount, x + 56, 368); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen wipe in", right to left +void ScreenEffects::vfx11(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int x = 312; x > -56; x -= 8) { + copyFxRect(surface, x, 0, x + 64, 200); + setBlendedPalette(palette, newPalette, colorCount, x + 56, 368); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen wipe in", top to bottom +void ScreenEffects::vfx12(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int y = -70; y < 312; y += 10) { + copyFxRect(surface, 0, y, 320, y + 80); + setBlendedPalette(palette, newPalette, colorCount, y + 70, 260); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen wipe in", bottom to top +void ScreenEffects::vfx13(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int y = 312; y > -70; y -= 10) { + copyFxRect(surface, 0, y, 320, y + 80); + setBlendedPalette(palette, newPalette, colorCount, y + 70, 260); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen open" effect +void ScreenEffects::vfx14(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + int16 x = 8, y = 5; + for (int i = 0; i < 27; i++) { + copyFxRect(surface, 160 - x, 100 - y, 160 + x, 100 + y); + x += 8; + y += 5; + setBlendedPalette(palette, newPalette, colorCount, i, 27); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +void ScreenEffects::vfx15(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + int16 x = 8; + for (int i = 0; i < 27; i++) { + copyFxRect(surface, 160 - x, 0, 160 + x, 200); + x += 8; + setBlendedPalette(palette, newPalette, colorCount, i, 27); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// Palette fadeout/fadein +void ScreenEffects::vfx17(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + + byte tempPalette[768]; + + bool savedPaletteLock = _screen->isPaletteLocked(); + _screen->setPaletteLock(false); + + memcpy(tempPalette, palette, 768); + + // Fade out to black + memset(palette, 0, 768); + for (int i = 0; i < 50; i++) { + setBlendedPalette(palette, newPalette, colorCount, i, 50); + _screen->updateScreenAndWait(25); + } + _screen->setRGBPalette(palette, 0, colorCount); + + memcpy(palette, tempPalette, 768); + + _screen->showWorkScreen(); + + // Fade from black to palette + memset(newPalette, 0, 768); + for (int i = 0; i < 50; i++) { + setBlendedPalette(palette, newPalette, colorCount, i, 50); + _screen->updateScreenAndWait(25); + } + _screen->setRGBPalette(palette, 0, colorCount); + + _screen->setPaletteLock(savedPaletteLock); + +} + + +} // End of namespace Made diff --git a/engines/made/screenfx.h b/engines/made/screenfx.h new file mode 100644 index 0000000000..e5023621ae --- /dev/null +++ b/engines/made/screenfx.h @@ -0,0 +1,70 @@ +/* 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 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$ + * + */ + +#ifndef MADE_SCREENFX_H +#define MADE_SCREENFX_H + +#include "common/endian.h" +#include "common/util.h" +#include "common/rect.h" + +#include "graphics/surface.h" + +#include "made/made.h" +#include "made/screen.h" + +namespace Made { + +class ScreenEffects { +public: + ScreenEffects(Screen *screen); + void run(int16 effectNum, Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void flash(int count, byte *palette, int colorCount); +private: + Screen *_screen; + byte _fxPalette[768]; + static const byte vfxOffsTable[64]; + static const byte vfxOffsIndexTable[8]; + const byte *vfxOffsTablePtr; + int16 vfxX1, vfxY1, vfxWidth, vfxHeight; + void setPalette(byte *palette); + void setBlendedPalette(byte *palette, byte *newPalette, int colorCount, int16 value, int16 maxValue); + void copyFxRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2); + void copyRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2); + void vfx00(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx02(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx09(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx10(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx11(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx12(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx13(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx14(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx15(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx17(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); +}; + +} // End of namespace Made + +#endif /* MADE_H */ diff --git a/engines/made/script.cpp b/engines/made/script.cpp index 74dc9e0d9f..6f4ff7ace3 100644 --- a/engines/made/script.cpp +++ b/engines/made/script.cpp @@ -91,96 +91,92 @@ int16 *ScriptStack::getStackPtr() { /* ScriptInterpreter */ ScriptInterpreter::ScriptInterpreter(MadeEngine *vm) : _vm(vm) { -#define COMMAND(x) { &ScriptInterpreter::x, #x } +#ifdef DUMP_SCRIPTS +#define COMMAND(x, sig) { &ScriptInterpreter::x, #x, sig } +#else +#define COMMAND(x, sig) { &ScriptInterpreter::x, #x} +#endif static CommandEntry commandProcs[] = { /* 01 */ - COMMAND(cmd_branchTrue), - COMMAND(cmd_branchFalse), - COMMAND(cmd_branch), - COMMAND(cmd_true), + COMMAND(cmd_branchTrue, "W"), + COMMAND(cmd_branchFalse, "W"), + COMMAND(cmd_branch, "W"), + COMMAND(cmd_true, ""), /* 05 */ - COMMAND(cmd_false), - COMMAND(cmd_push), - COMMAND(cmd_not), - COMMAND(cmd_add), + COMMAND(cmd_false, ""), + COMMAND(cmd_push, ""), + COMMAND(cmd_not, ""), + COMMAND(cmd_add, ""), /* 09 */ - COMMAND(cmd_sub), - COMMAND(cmd_mul), - COMMAND(cmd_div), - COMMAND(cmd_mod), + COMMAND(cmd_sub, ""), + COMMAND(cmd_mul, ""), + COMMAND(cmd_div, ""), + COMMAND(cmd_mod, ""), /* 13 */ - COMMAND(cmd_band), - COMMAND(cmd_bor), - COMMAND(cmd_bnot), - COMMAND(cmd_lt), + COMMAND(cmd_band, ""), + COMMAND(cmd_bor, ""), + COMMAND(cmd_bnot, ""), + COMMAND(cmd_lt, ""), /* 17 */ - COMMAND(cmd_eq), - COMMAND(cmd_gt), - COMMAND(cmd_loadConstant), - COMMAND(cmd_loadVariable), + COMMAND(cmd_eq, ""), + COMMAND(cmd_gt, ""), + COMMAND(cmd_loadConstant, "w"), + COMMAND(cmd_loadVariable, "w"), /* 21 */ - COMMAND(cmd_getObjectProperty), - COMMAND(cmd_setObjectProperty), - COMMAND(cmd_set), - COMMAND(cmd_print), + COMMAND(cmd_getObjectProperty, ""), + COMMAND(cmd_setObjectProperty, ""), + COMMAND(cmd_set, "w"), + COMMAND(cmd_print, ""), /* 25 */ - COMMAND(cmd_terpri), - COMMAND(cmd_printNumber), - COMMAND(cmd_vref), - COMMAND(cmd_vset), + COMMAND(cmd_terpri, ""), + COMMAND(cmd_printNumber, ""), + COMMAND(cmd_vref, ""), + COMMAND(cmd_vset, ""), /* 29 */ - COMMAND(cmd_vsize), - COMMAND(cmd_exit), - COMMAND(cmd_return), - COMMAND(cmd_call), + COMMAND(cmd_vsize, ""), + COMMAND(cmd_exit, ""), + COMMAND(cmd_return, ""), + COMMAND(cmd_call, "b"), /* 33 */ - COMMAND(cmd_svar), - COMMAND(cmd_sset), - COMMAND(cmd_split), - COMMAND(cmd_snlit), + COMMAND(cmd_svar, ""), + COMMAND(cmd_sset, ""), + COMMAND(cmd_split, ""), + COMMAND(cmd_snlit, ""), /* 37 */ - COMMAND(cmd_yorn), - COMMAND(cmd_save), - COMMAND(cmd_restore), - COMMAND(cmd_arg), + COMMAND(cmd_yorn, ""), + COMMAND(cmd_save, ""), + COMMAND(cmd_restore, ""), + COMMAND(cmd_arg, "b"), /* 41 */ - COMMAND(cmd_aset), - COMMAND(cmd_tmp), - COMMAND(cmd_tset), - COMMAND(cmd_tspace), + COMMAND(cmd_aset, "b"), + COMMAND(cmd_tmp, "b"), + COMMAND(cmd_tset, "b"), + COMMAND(cmd_tspace, "b"), /* 45 */ - COMMAND(cmd_class), - COMMAND(cmd_objectp), - COMMAND(cmd_vectorp), - COMMAND(cmd_restart), + COMMAND(cmd_class, ""), + COMMAND(cmd_objectp, ""), + COMMAND(cmd_vectorp, ""), + COMMAND(cmd_restart, ""), /* 49 */ - COMMAND(cmd_rand), - COMMAND(cmd_randomize), - COMMAND(cmd_send), - COMMAND(cmd_extend), + COMMAND(cmd_rand, ""), + COMMAND(cmd_randomize, ""), + COMMAND(cmd_send, "b"), + COMMAND(cmd_extend, "Eb"), /* 53 */ - COMMAND(cmd_catch), - COMMAND(cmd_cdone), - COMMAND(cmd_throw), - COMMAND(cmd_functionp), + COMMAND(cmd_catch, ""), + COMMAND(cmd_cdone, ""), + COMMAND(cmd_throw, ""), + COMMAND(cmd_functionp, ""), /* 57 */ - COMMAND(cmd_le), - COMMAND(cmd_ge), - COMMAND(cmd_varx), - COMMAND(cmd_setx) + COMMAND(cmd_le, ""), + COMMAND(cmd_ge, ""), + COMMAND(cmd_varx, ""), + COMMAND(cmd_setx, "") }; _commands = commandProcs; _commandsMax = ARRAYSIZE(commandProcs) + 1; - if (_vm->getGameID() == GID_RTZ) - _functions = new ScriptFunctionsRtz(_vm); - else if (_vm->getGameID() == GID_LGOP2) - _functions = new ScriptFunctionsLgop2(_vm); - else if (_vm->getGameID() == GID_MANHOLE) - _functions = new ScriptFunctionsMhne(_vm); - else - error("Unsupported GameID"); - + _functions = new ScriptFunctions(_vm); _functions->setupExternalsTable(); #undef COMMAND @@ -191,8 +187,7 @@ ScriptInterpreter::~ScriptInterpreter() { } void ScriptInterpreter::runScript(int16 scriptObjectIndex) { - - _terminated = false; + _vm->_quit = false; _runningScriptObjectIndex = scriptObjectIndex; _localStackPos = _stack.getStackPos(); @@ -200,16 +195,19 @@ void ScriptInterpreter::runScript(int16 scriptObjectIndex) { _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData(); _codeIp = _codeBase; - while (!_terminated) { + while (!_vm->_quit) { + + _vm->handleEvents(); + byte opcode = readByte(); if (opcode >= 1 && opcode <= _commandsMax) { - debug(4, "opcode = %s\n", _commands[opcode - 1].desc); + debug(4, "[%04X:%04X] %s", _runningScriptObjectIndex, (uint) (_codeIp - _codeBase), _commands[opcode - 1].desc); (this->*_commands[opcode - 1].proc)(); } else { - warning("ScriptInterpreter::runScript(%d) Unknown opcode %02X\n", _runningScriptObjectIndex, opcode); + warning("ScriptInterpreter::runScript(%d) Unknown opcode %02X", _runningScriptObjectIndex, opcode); } + } - } byte ScriptInterpreter::readByte() { @@ -219,7 +217,7 @@ byte ScriptInterpreter::readByte() { int16 ScriptInterpreter::readInt16() { int16 temp = (int16)READ_LE_UINT16(_codeIp); _codeIp += 2; - debug(4, "readInt16() value = %04X\n", temp); + debug(4, "readInt16() value = %04X", temp); return temp; } @@ -330,14 +328,14 @@ void ScriptInterpreter::cmd_gt() { void ScriptInterpreter::cmd_loadConstant() { int16 value = readInt16(); - debug(4, "value = %04X (%d)\n", value, value); + debug(4, "value = %04X (%d)", value, value); _stack.setTop(value); } void ScriptInterpreter::cmd_loadVariable() { int16 variable = readInt16(); int16 value = _vm->_dat->getVar(variable); - debug(4, "variable = %d; value = %d (%04X)\n", variable, value, value); fflush(stdout); + debug(4, "variable = %d; value = %d (%04X)", variable, value, value); _stack.setTop(value); } @@ -345,7 +343,7 @@ void ScriptInterpreter::cmd_getObjectProperty() { int16 propertyId = _stack.pop(); int16 objectIndex = _stack.top(); int16 value = _vm->_dat->getObjectProperty(objectIndex, propertyId); - debug(4, "value = %04X(%d)\n", value, value); + debug(4, "value = %04X(%d)", value, value); _stack.setTop(value); } @@ -359,15 +357,14 @@ void ScriptInterpreter::cmd_setObjectProperty() { void ScriptInterpreter::cmd_set() { int16 variable = readInt16(); - debug(4, "var(%d) = %04d (%d)\n", variable, _stack.top(), _stack.top()); + debug(4, "var(%d) = %04d (%d)", variable, _stack.top(), _stack.top()); _vm->_dat->setVar(variable, _stack.top()); } void ScriptInterpreter::cmd_print() { // TODO: This opcode was used for printing debug messages - Object *obj = _vm->_dat->getObject(_stack.top()); - const char *text = obj->getString(); - debug(4, "%s", text); fflush(stdout); + const char *text = _vm->_dat->getObjectString(_stack.top()); + debug(4, "%s", text); _stack.setTop(0); } @@ -386,20 +383,20 @@ void ScriptInterpreter::cmd_vref() { int16 value = 0; int16 index = _stack.pop(); int16 objectIndex = _stack.top(); - debug(4, "index = %d; objectIndex = %d\n", index, objectIndex); fflush(stdout); + debug(4, "index = %d; objectIndex = %d", index, objectIndex); if (objectIndex > 0) { Object *obj = _vm->_dat->getObject(objectIndex); value = obj->getVectorItem(index); } _stack.setTop(value); - debug(4, "--> value = %d\n", value); fflush(stdout); + debug(4, "--> value = %d", value); } void ScriptInterpreter::cmd_vset() { int16 value = _stack.pop(); int16 index = _stack.pop(); int16 objectIndex = _stack.top(); - debug(4, "index = %d; objectIndex = %d; value = %d\n", index, objectIndex, value); fflush(stdout); + debug(4, "index = %d; objectIndex = %d; value = %d", index, objectIndex, value); if (objectIndex > 0) { Object *obj = _vm->_dat->getObject(objectIndex); obj->setVectorItem(index, value); @@ -418,11 +415,17 @@ void ScriptInterpreter::cmd_vsize() { } void ScriptInterpreter::cmd_exit() { - warning("Unimplemented command: cmd_exit"); + _vm->_quit = true; } void ScriptInterpreter::cmd_return() { - // TODO: Check if returning from main function + + // Check if returning from main function + if (_localStackPos == kScriptStackSize) { + _vm->_quit = true; + return; + } + int16 funcResult = _stack.top(); _stack.setStackPos(_localStackPos); _localStackPos = kScriptStackLimit - _stack.pop(); @@ -432,95 +435,115 @@ void ScriptInterpreter::cmd_return() { byte argc = _stack.pop(); _stack.free(argc); _stack.setTop(funcResult); - debug(4, "LEAVE: stackPtr = %d; _localStackPos = %d\n\n\n", _stack.getStackPos(), _localStackPos); + debug(4, "LEAVE: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos); } void ScriptInterpreter::cmd_call() { - debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos); + debug(4, "\nENTER: stackPtr = %d; _localStackPos = %d", _stack.getStackPos(), _localStackPos); byte argc = readByte(); + _stack.push(argc); _stack.push(_codeIp - _codeBase); _stack.push(_runningScriptObjectIndex); _stack.push(kScriptStackLimit - _localStackPos); _localStackPos = _stack.getStackPos(); _runningScriptObjectIndex = _stack.peek(_localStackPos + argc + 4); - debug(4, "argc = %d; _runningScriptObjectIndex = %04X\n", argc, _runningScriptObjectIndex); fflush(stdout); + debug(4, "argc = %d; _runningScriptObjectIndex = %04X", argc, _runningScriptObjectIndex); _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData(); _codeIp = _codeBase; } void ScriptInterpreter::cmd_svar() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_svar"); } void ScriptInterpreter::cmd_sset() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_sset"); } void ScriptInterpreter::cmd_split() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_split"); } void ScriptInterpreter::cmd_snlit() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_snlit"); } void ScriptInterpreter::cmd_yorn() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_yorn"); } void ScriptInterpreter::cmd_save() { - warning("Unimplemented command: cmd_save"); - _stack.setTop(0); + int16 result = 0; + int16 stringOfs = _stack.top(); + const char *filename = _vm->_dat->getString(stringOfs); + result = _vm->_dat->savegame(filename, "", 0); + _stack.setTop(result); } void ScriptInterpreter::cmd_restore() { - warning("Unimplemented command: cmd_restore"); + int16 result = 0; + int16 stringOfs = _stack.top(); + const char *filename = _vm->_dat->getString(stringOfs); + result = _vm->_dat->loadgame(filename, 0); + _stack.setTop(result); } void ScriptInterpreter::cmd_arg() { int16 argIndex = readByte(); - debug(4, "argIndex = %d; value = %04X (%d)\n", argIndex, _stack.peek(_localStackPos + 4 + argIndex), _stack.peek(_localStackPos + 4 + argIndex)); + debug(4, "argIndex = %d; value = %04X (%d)", argIndex, _stack.peek(_localStackPos + 4 + argIndex), _stack.peek(_localStackPos + 4 + argIndex)); _stack.setTop(_stack.peek(_localStackPos + 4 + argIndex)); } void ScriptInterpreter::cmd_aset() { int16 argIndex = readByte(); - debug(4, "argIndex = %d; value = %d\n", argIndex, _stack.peek(_localStackPos + 4 + argIndex)); + debug(4, "argIndex = %d; value = %d", argIndex, _stack.peek(_localStackPos + 4 + argIndex)); _stack.poke(_localStackPos + 4 + argIndex, _stack.top()); } void ScriptInterpreter::cmd_tmp() { int16 tempIndex = readByte(); - debug(4, "tempIndex = %d; value = %d\n", tempIndex, _stack.peek(_localStackPos - tempIndex - 1)); + debug(4, "tempIndex = %d; value = %d", tempIndex, _stack.peek(_localStackPos - tempIndex - 1)); _stack.setTop(_stack.peek(_localStackPos - tempIndex - 1)); } void ScriptInterpreter::cmd_tset() { int16 tempIndex = readByte(); - debug(4, "tempIndex = %d; value = %d\n", tempIndex, _stack.top()); + debug(4, "tempIndex = %d; value = %d", tempIndex, _stack.top()); _stack.poke(_localStackPos - tempIndex - 1, _stack.top()); } void ScriptInterpreter::cmd_tspace() { int16 tempCount = readByte(); - debug(4, "tempCount = %d\n", tempCount); + debug(4, "tempCount = %d", tempCount); _stack.alloc(tempCount); } void ScriptInterpreter::cmd_class() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_class"); } void ScriptInterpreter::cmd_objectp() { - warning("Unimplemented command: cmd_objectp"); + Object *obj = _vm->_dat->getObject(_stack.top()); + if (obj->isObject()) + _stack.setTop(-1); + else + _stack.setTop(0); } void ScriptInterpreter::cmd_vectorp() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_vectorp"); } void ScriptInterpreter::cmd_restart() { + // TODO: Used in RTZ warning("Unimplemented command: cmd_restart"); } @@ -535,11 +558,11 @@ void ScriptInterpreter::cmd_randomize() { void ScriptInterpreter::cmd_send() { - debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos); + debug(4, "\nENTER: stackPtr = %d; _localStackPos = %d", _stack.getStackPos(), _localStackPos); byte argc = readByte(); - debug(4, "argc = %d\n", argc); + debug(4, "argc = %d", argc); _stack.push(argc); _stack.push(_codeIp - _codeBase); @@ -550,7 +573,7 @@ void ScriptInterpreter::cmd_send() { int16 propertyId = _stack.peek(_localStackPos + argc + 2); int16 objectIndex = _stack.peek(_localStackPos + argc + 4); - debug(4, "objectIndex = %d (%04X); propertyId = %d(%04X)\n", objectIndex, objectIndex, propertyId, propertyId); fflush(stdout); + debug(4, "objectIndex = %d (%04X); propertyId = %d(%04X)", objectIndex, objectIndex, propertyId, propertyId); if (objectIndex != 0) { objectIndex = _vm->_dat->getObject(objectIndex)->getClass(); @@ -558,7 +581,7 @@ void ScriptInterpreter::cmd_send() { objectIndex = _stack.peek(_localStackPos + argc + 3); } - debug(4, "--> objectIndex = %d(%04X)\n", objectIndex, objectIndex); fflush(stdout); + debug(4, "--> objectIndex = %d(%04X)", objectIndex, objectIndex); if (objectIndex != 0) { _runningScriptObjectIndex = _vm->_dat->getObjectProperty(objectIndex, propertyId); @@ -583,13 +606,12 @@ void ScriptInterpreter::cmd_extend() { byte argc = readByte(); int16 *argv = _stack.getStackPtr(); - //debug(4, "func = %d (%s); argc = %d\n", func, extendFuncNames[func], argc); - debug(4, "func = %d; argc = %d\n", func, argc); + debug(4, "func = %d (%s); argc = %d", func, _functions->getFuncName(func), argc); for (int i = 0; i < argc; i++) - debug(4, "argv[%02d] = %04X (%d)\n", i, argv[i], argv[i]); + debug(2, "argv[%02d] = %04X (%d)", i, argv[i], argv[i]); int16 result = _functions->callFunction(func, argc, argv); - debug(4, "result = %04X (%d)\n", result, result); + debug(2, "result = %04X (%d)", result, result); _stack.free(argc); @@ -598,18 +620,22 @@ void ScriptInterpreter::cmd_extend() { } void ScriptInterpreter::cmd_catch() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_catch"); } void ScriptInterpreter::cmd_cdone() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_cdone"); } void ScriptInterpreter::cmd_throw() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_throw"); } void ScriptInterpreter::cmd_functionp() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_functionp"); } @@ -630,11 +656,133 @@ void ScriptInterpreter::cmd_ge() { } void ScriptInterpreter::cmd_varx() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_varx"); } void ScriptInterpreter::cmd_setx() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_setx"); } +#ifdef DUMP_SCRIPTS +void ScriptInterpreter::dumpScript(int16 objectIndex, int *opcodeStats, int *externStats) { + + debug(1, "Dumping code for object %04X", objectIndex); + + Object *obj = _vm->_dat->getObject(objectIndex); + byte *code = obj->getData(), *codeStart = code, *codeEnd = code + obj->getSize(); + + while (code < codeEnd) { + byte opcode = *code++; + if (opcode >= 1 && opcode <= _commandsMax) { + Common::String codeLine; + const char *desc = _commands[opcode - 1].desc; + const char *sig = _commands[opcode - 1].sig; + int valueType; /* 0: dec; 1: hex; 2: extended function */ + int16 value; + char tempStr[32]; + opcodeStats[opcode - 1]++; + snprintf(tempStr, 32, "[%04X] ", (uint16)(code - codeStart - 1)); + codeLine += tempStr; + codeLine += desc; + for (; *sig != '\0'; sig++) { + codeLine += " "; + switch (*sig) { + case 'b': + valueType = 0; + value = *code++; + break; + case 'B': + valueType = 1; + value = *code++; + break; + case 'w': + valueType = 0; + value = READ_LE_UINT16(code); + code += 2; + break; + case 'W': + valueType = 1; + value = READ_LE_UINT16(code); + code += 2; + break; + case 'E': + valueType = 2; + value = *code++; + break; + } + switch (valueType) { + case 0: + snprintf(tempStr, 32, "%d", value); + break; + case 1: + snprintf(tempStr, 32, "0x%X", value); + break; + case 2: + if (value < _functions->getCount()) { + snprintf(tempStr, 32, "%s", _functions->getFuncName(value)); + externStats[value]++; + } else { + snprintf(tempStr, 32, "invalid: %d", value); + } + break; + } + codeLine += tempStr; + } + debug(1, "%s", codeLine.c_str()); + } else { + error("ScriptInterpreter::dumpScript(%d) Unknown opcode %02X", objectIndex, opcode); + } + } + debug(1, "-------------------------------------------"); +} + +void ScriptInterpreter::dumpAllScripts() { + int *opcodeStats = new int[_commandsMax - 1]; + int *externStats = new int[_functions->getCount()]; + + for (int i = 0; i < _commandsMax; i++) + opcodeStats[i] = 0; + for (int i = 0; i < _functions->getCount(); i++) + externStats[i] = 0; + + for (uint objectIndex = 1; objectIndex <= _vm->_dat->getObjectCount(); objectIndex++) { + Object *obj = _vm->_dat->getObject(objectIndex); + // Check if it's a byte array which might contain code + if (obj->getClass() != 0x7FFF) + continue; + // Code objects aren't excplicitly marked as such, we need to check if + // the last byte is a cmd_return opcode. + byte *retByte = obj->getData() + obj->getSize() - 1; + if (*retByte == 0x1F) { + dumpScript(objectIndex, opcodeStats, externStats); + } + } + + debug(1, "OPCODE statistics:"); + for (int i = 0; i < _commandsMax - 1; i++) + if (opcodeStats[i] > 0) + debug(1, "%-30s: %d", _commands[i].desc, opcodeStats[i]); + debug(1, "UNUSED OPCODE statistics:"); + for (int i = 0; i < _commandsMax - 1; i++) + if (opcodeStats[i] == 0) + debug(1, "%-30s: %d", _commands[i].desc, opcodeStats[i]); + debug(1, "."); + + debug(1, "EXTERN statistics (%d):", _functions->getCount()); + for (int i = 0; i < _functions->getCount(); i++) + if (externStats[i] > 0) + debug(1, "%-30s: %d", _functions->getFuncName(i), externStats[i]); + debug(1, "UNUSED EXTERN statistics (%d):", _functions->getCount()); + for (int i = 0; i < _functions->getCount(); i++) + if (externStats[i] == 0) + debug(1, "%-30s: %d", _functions->getFuncName(i), externStats[i]); + debug(1, "."); + + delete[] opcodeStats; + delete[] externStats; +} +#endif + } // End of namespace Made diff --git a/engines/made/script.h b/engines/made/script.h index 6c031f8708..459a088cb8 100644 --- a/engines/made/script.h +++ b/engines/made/script.h @@ -32,6 +32,11 @@ namespace Made { +// Define this to dump all game scripts and a usage statistic of all +// opcodes/extended functions instead of running the actual game. +// Then run ScummVM with debuglevel 1. +//#define DUMP_SCRIPTS + class MadeEngine; class ScriptFunctions; @@ -63,6 +68,8 @@ public: ScriptInterpreter(MadeEngine *vm); ~ScriptInterpreter(); void runScript(int16 scriptObjectIndex); + void dumpScript(int16 objectIndex, int *opcodeStats, int *externStats); + void dumpAllScripts(); protected: MadeEngine *_vm; @@ -81,6 +88,9 @@ protected: struct CommandEntry { CommandProc proc; const char *desc; +#ifdef DUMP_SCRIPTS + const char *sig; +#endif }; const CommandEntry *_commands; diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index 7fc61ee410..932447a1eb 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -26,8 +26,8 @@ #include "common/endian.h" #include "common/util.h" #include "common/events.h" - #include "graphics/cursorman.h" +#include "sound/audiocd.h" #include "made/made.h" #include "made/resource.h" @@ -40,386 +40,414 @@ namespace Made { -int16 ScriptFunctions::callFunction(uint16 index, int16 argc, int16 *argv) { - if (index >= _externalFuncs.size()) { - // TODO: ERROR! - return 0; - } +typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctions> ExternalScriptFunc; +#define External(x) \ + _externalFuncs.push_back(new ExternalScriptFunc(this, &ScriptFunctions::x)); \ + _externalFuncNames.push_back(#x); +void ScriptFunctions::setupExternalsTable() { + + External(sfSystemCall); + External(sfInitGraf); + External(sfRestoreGraf); + External(sfDrawPicture); + External(sfClearScreen); + External(sfShowPage); + External(sfPollEvent); + External(sfGetMouseX); + External(sfGetMouseY); + External(sfGetKey); + External(sfSetVisualEffect); + External(sfPlaySound); + External(sfPlayMusic); + External(sfStopMusic); + External(sfIsMusicPlaying); + External(sfSetTextPos); + External(sfFlashScreen); + External(sfPlayNote); + External(sfStopNote); + External(sfPlayTele); + External(sfStopTele); + External(sfHideMouseCursor); + External(sfShowMouseCursor); + External(sfGetMusicBeat); + External(sfSetScreenLock); + External(sfAddSprite); + External(sfFreeAnim); + External(sfDrawSprite); + External(sfEraseSprites); + External(sfUpdateSprites); + External(sfGetTimer); + External(sfSetTimer); + External(sfResetTimer); + External(sfAllocTimer); + External(sfFreeTimer); + External(sfSetPaletteLock); + External(sfSetFont); + External(sfDrawText); + External(sfHomeText); + External(sfSetTextRect); + External(sfSetTextXY); + External(sfSetFontDropShadow); + External(sfSetFontColor); + External(sfSetFontOutline); + External(sfLoadMouseCursor); + External(sfSetSpriteGround); + External(sfLoadResText); - fflush(stdout); - //g_system->delayMillis(2000); + if (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_RODNEY) { + External(sfAddScreenMask); + External(sfSetSpriteMask); + } else if (_vm->getGameID() == GID_RTZ) { + External(sfSetClipArea); + External(sfSetSpriteClip); + } + + External(sfSoundPlaying); + External(sfStopSound); + External(sfPlayVoice); + + if (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_RTZ) { + External(sfPlayCd); + External(sfStopCd); + External(sfGetCdStatus); + External(sfGetCdTime); + External(sfPlayCdSegment); + } - return (*_externalFuncs[index])(argc, argv); -} - -typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctionsRtz> ExternalFuncRtz; -#define External(x) ExternalFuncRtz(this, &ScriptFunctionsRtz::x) -void ScriptFunctionsRtz::setupExternalsTable() { - static const ExternalFuncRtz externalsTable[] = { - External(o1_SYSTEM), - External(o1_INITGRAF), - External(o1_RESTOREGRAF), - External(o1_DRAWPIC), - External(o1_CLS), - External(o1_SHOWPAGE), - External(o1_EVENT), - External(o1_EVENTX), - External(o1_EVENTY), - External(o1_EVENTKEY), - External(o1_VISUALFX), - External(o1_PLAYSND), - External(o1_PLAYMUS), - External(o1_STOPMUS), - External(o1_ISMUS), - External(o1_TEXTPOS), - External(o1_FLASH), - External(o1_PLAYNOTE), - External(o1_STOPNOTE), - External(o1_PLAYTELE), - External(o1_STOPTELE), - External(o1_HIDECURS), - External(o1_SHOWCURS), - External(o1_MUSICBEAT), - External(o1_SCREENLOCK), - External(o1_ADDSPRITE), - External(o1_FREEANIM), - External(o1_DRAWSPRITE), - External(o1_ERASESPRITES), - External(o1_UPDATESPRITES), - External(o1_GETTIMER), - External(o1_SETTIMER), - External(o1_RESETTIMER), - External(o1_ALLOCTIMER), - External(o1_FREETIMER), - External(o1_PALETTELOCK), - External(o1_FONT), - External(o1_DRAWTEXT), - External(o1_HOMETEXT), - External(o1_TEXTRECT), - External(o1_TEXTXY), - External(o1_DROPSHADOW), - External(o1_TEXTCOLOR), - External(o1_OUTLINE), - External(o1_LOADCURSOR), - External(o1_SETGROUND), - External(o1_RESTEXT), - External(o1_CLIPAREA), - External(o1_SETCLIP), - External(o1_ISSND), - External(o1_STOPSND), - External(o1_PLAYVOICE), - External(o1_CDPLAY), - External(o1_STOPCD), - External(o1_CDSTATUS), - External(o1_CDTIME), - External(o1_CDPLAYSEG), - External(o1_PRINTF), - External(o1_MONOCLS), - External(o1_SNDENERGY), - External(o1_CLEARTEXT), - External(o1_ANIMTEXT), - External(o1_TEXTWIDTH), - External(o1_PLAYMOVIE), - External(o1_LOADSND), - External(o1_LOADMUS), - External(o1_LOADPIC), - External(o1_MUSICVOL), - External(o1_RESTARTEVENTS), - External(o1_PLACESPRITE), - External(o1_PLACETEXT), - External(o1_DELETECHANNEL), - External(o1_CHANNELTYPE), - External(o1_SETSTATE), - External(o1_SETLOCATION), - External(o1_SETCONTENT), - External(o1_EXCLUDEAREA), - External(o1_SETEXCLUDE), - External(o1_GETSTATE), - External(o1_PLACEANIM), - External(o1_SETFRAME), - External(o1_GETFRAME), - External(o1_GETFRAMECOUNT), - External(o1_PICWIDTH), - External(o1_PICHEIGHT), - External(o1_SOUNDRATE), - External(o1_DRAWANIMPIC), - External(o1_LOADANIM), - External(o1_READTEXT), - External(o1_READMENU), - External(o1_DRAWMENU), - External(o1_MENUCOUNT), - External(o1_SAVEGAME), - External(o1_LOADGAME), - External(o1_GAMENAME), - External(o1_SHAKESCREEN), - External(o1_PLACEMENU), - External(o1_SETVOLUME), - External(o1_WHATSYNTH), - External(o1_SLOWSYSTEM) - }; - - for (int i = 0; i < ARRAYSIZE(externalsTable); ++i) - _externalFuncs.push_back(&externalsTable[i]); + if (_vm->getGameID() == GID_RTZ) { + External(sfPrintf); + External(sfClearMono); + External(sfGetSoundEnergy); + External(sfClearText); + External(sfAnimText); + External(sfGetTextWidth); + External(sfPlayMovie); + External(sfLoadSound); + External(sfLoadMusic); + External(sfLoadPicture); + External(sfSetMusicVolume); + External(sfRestartEvents); + External(sfPlaceSprite); + External(sfPlaceText); + External(sfDeleteChannel); + External(sfGetChannelType); + External(sfSetChannelState); + External(sfSetChannelLocation); + External(sfSetChannelContent); + External(sfSetExcludeArea); + External(sfSetSpriteExclude); + External(sfGetChannelState); + External(sfPlaceAnim); + External(sfSetAnimFrame); + External(sfGetAnimFrame); + External(sfGetAnimFrameCount); + External(sfGetPictureWidth); + External(sfGetPictureHeight); + External(sfSetSoundRate); + External(sfDrawAnimPic); + External(sfLoadAnim); + External(sfReadText); + External(sfReadMenu); + External(sfDrawMenu); + External(sfGetMenuCount); + External(sfSaveGame); + External(sfLoadGame); + External(sfGetGameDescription); + External(sfShakeScreen); + External(sfPlaceMenu); + External(sfSetSoundVolume); + External(sfGetSynthType); + External(sfIsSlowSystem); + } } #undef External -int16 ScriptFunctionsRtz::o1_SYSTEM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSystemCall(int16 argc, int16 *argv) { // This opcode is empty. return 0; } -int16 ScriptFunctionsRtz::o1_INITGRAF(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfInitGraf(int16 argc, int16 *argv) { // This opcode is empty. return 0; } -int16 ScriptFunctionsRtz::o1_RESTOREGRAF(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfRestoreGraf(int16 argc, int16 *argv) { // This opcode is empty. return 0; } -int16 ScriptFunctionsRtz::o1_DRAWPIC(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfDrawPicture(int16 argc, int16 *argv) { return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_CLS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfClearScreen(int16 argc, int16 *argv) { + if (_vm->_screen->isScreenLocked()) + return 0; + if (_vm->_autoStopSound) { + _vm->_mixer->stopHandle(_audioStreamHandle); + _vm->_autoStopSound = false; + } _vm->_screen->clearScreen(); return 0; } -int16 ScriptFunctionsRtz::o1_SHOWPAGE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfShowPage(int16 argc, int16 *argv) { _vm->_screen->show(); return 0; } -int16 ScriptFunctionsRtz::o1_EVENT(int16 argc, int16 *argv) { - - Common::Event event; - Common::EventManager *eventMan = g_system->getEventManager(); - - int16 eventNum = 0; - - if (eventMan->pollEvent(event)) { - switch (event.type) { - - case Common::EVENT_MOUSEMOVE: - _vm->_eventMouseX = event.mouse.x; - _vm->_eventMouseY = event.mouse.y; - break; - - case Common::EVENT_LBUTTONDOWN: - eventNum = 1; - break; - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } +int16 ScriptFunctions::sfPollEvent(int16 argc, int16 *argv) { _vm->_system->updateScreen(); + int16 eventNum = _vm->_eventNum; + _vm->_eventNum = 0; return eventNum; } -int16 ScriptFunctionsRtz::o1_EVENTX(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetMouseX(int16 argc, int16 *argv) { return _vm->_eventMouseX; } -int16 ScriptFunctionsRtz::o1_EVENTY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetMouseY(int16 argc, int16 *argv) { return _vm->_eventMouseY; } -int16 ScriptFunctionsRtz::o1_EVENTKEY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetKey(int16 argc, int16 *argv) { return _vm->_eventKey; } -int16 ScriptFunctionsRtz::o1_VISUALFX(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetVisualEffect(int16 argc, int16 *argv) { _vm->_screen->setVisualEffectNum(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - +int16 ScriptFunctions::sfPlaySound(int16 argc, int16 *argv) { + int16 soundNum = argv[0]; + _vm->_autoStopSound = false; + _vm->_mixer->stopHandle(_audioStreamHandle); if (argc > 1) { soundNum = argv[1]; - loop = (argv[0] == 1); + _vm->_autoStopSound = (argv[0] == 1); } - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } + _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, + _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, false)); } - return 0; } -int16 ScriptFunctionsRtz::o1_PLAYMUS(int16 argc, int16 *argv) { - int16 musicNum = argv[0]; - if (musicNum > 0) { - XmidiResource *xmidi = _vm->_res->getXmidi(musicNum); - _vm->_music->play(xmidi); - _vm->_res->freeResource(xmidi); +int16 ScriptFunctions::sfPlayMusic(int16 argc, int16 *argv) { + // TODO: Music in LGOP2 and Manhole isn't supported yet + if (_vm->getGameID() == GID_RTZ) { + int16 musicNum = argv[0]; + if (musicNum > 0) { + _musicRes = _vm->_res->getXmidi(musicNum); + if (_musicRes) + _vm->_music->playXMIDI(_musicRes); + } } return 0; } -int16 ScriptFunctionsRtz::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); +int16 ScriptFunctions::sfStopMusic(int16 argc, int16 *argv) { + if (_vm->_music->isPlaying() && _musicRes) { + _vm->_music->stop(); + _vm->_res->freeResource(_musicRes); + _musicRes = NULL; + } return 0; } -int16 ScriptFunctionsRtz::o1_ISMUS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfIsMusicPlaying(int16 argc, int16 *argv) { if (_vm->_music->isPlaying()) return 1; else return 0; } -int16 ScriptFunctionsRtz::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); +int16 ScriptFunctions::sfSetTextPos(int16 argc, int16 *argv) { + // Used in Manhole:NE + //warning("Unimplemented opcode: sfSetTextPos"); // This seems to be some kind of low-level opcode. // The original engine calls int 10h to set the VGA cursor position. + // Since this seems to be used for debugging purposes only it's left out. return 0; } -int16 ScriptFunctionsRtz::o1_FLASH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfFlashScreen(int16 argc, int16 *argv) { _vm->_screen->flash(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); +int16 ScriptFunctions::sfPlayNote(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfPlayNote"); return 0; } -int16 ScriptFunctionsRtz::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); +int16 ScriptFunctions::sfStopNote(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfStopNote"); return 0; } -int16 ScriptFunctionsRtz::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); +int16 ScriptFunctions::sfPlayTele(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfPlayTele"); return 0; } -int16 ScriptFunctionsRtz::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); +int16 ScriptFunctions::sfStopTele(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfStopTele"); return 0; } -int16 ScriptFunctionsRtz::o1_HIDECURS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfHideMouseCursor(int16 argc, int16 *argv) { _vm->_system->showMouse(false); return 0; } -int16 ScriptFunctionsRtz::o1_SHOWCURS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfShowMouseCursor(int16 argc, int16 *argv) { _vm->_system->showMouse(true); return 0; } -int16 ScriptFunctionsRtz::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); +int16 ScriptFunctions::sfGetMusicBeat(int16 argc, int16 *argv) { + // This is called loads of times in the intro of the floppy version + // of RtZ. Not sure what it does. Commented out to reduce spam + //warning("Unimplemented opcode: sfGetMusicBeat"); return 0; } -int16 ScriptFunctionsRtz::o1_SCREENLOCK(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetScreenLock(int16 argc, int16 *argv) { _vm->_screen->setScreenLock(argv[0] != 0); return 0; } -int16 ScriptFunctionsRtz::o1_ADDSPRITE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ADDSPRITE"); - //_vm->_screen->addSprite(argv[0]); - return 0; +int16 ScriptFunctions::sfAddSprite(int16 argc, int16 *argv) { + if (_vm->getGameID() == GID_RTZ) { + // Unused in RTZ + return 0; + } if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + return _vm->_screen->addToSpriteList(argv[2], argv[1], argv[0]); + } else { + return 0; + } } -int16 ScriptFunctionsRtz::o1_FREEANIM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfFreeAnim(int16 argc, int16 *argv) { _vm->_screen->clearChannels(); + if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + _vm->_screen->clearSpriteList(); + } return 0; } -int16 ScriptFunctionsRtz::o1_DRAWSPRITE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWSPRITE"); - return 0; +int16 ScriptFunctions::sfDrawSprite(int16 argc, int16 *argv) { + if (_vm->getGameID() == GID_RTZ) { + return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); + } if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + SpriteListItem item = _vm->_screen->getFromSpriteList(argv[2]); + int16 channelIndex = _vm->_screen->drawSprite(item.index, argv[1] - item.xofs, argv[0] - item.yofs); + _vm->_screen->setChannelUseMask(channelIndex); + return 0; + } else { + return 0; + } } -int16 ScriptFunctionsRtz::o1_ERASESPRITES(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfEraseSprites(int16 argc, int16 *argv) { _vm->_screen->clearChannels(); return 0; } -int16 ScriptFunctionsRtz::o1_UPDATESPRITES(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfUpdateSprites(int16 argc, int16 *argv) { _vm->_screen->updateSprites(); return 0; } -int16 ScriptFunctionsRtz::o1_GETTIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetTimer(int16 argc, int16 *argv) { return _vm->getTimer(argv[0]); } -int16 ScriptFunctionsRtz::o1_SETTIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetTimer(int16 argc, int16 *argv) { _vm->setTimer(argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_RESETTIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfResetTimer(int16 argc, int16 *argv) { _vm->resetTimer(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_ALLOCTIMER(int16 argc, int16 *argv) { - int16 timerNum = _vm->allocTimer(); - return timerNum; +int16 ScriptFunctions::sfAllocTimer(int16 argc, int16 *argv) { + return _vm->allocTimer(); } -int16 ScriptFunctionsRtz::o1_FREETIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfFreeTimer(int16 argc, int16 *argv) { _vm->freeTimer(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_PALETTELOCK(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetPaletteLock(int16 argc, int16 *argv) { _vm->_screen->setPaletteLock(argv[0] != 0); return 0; } -int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFont(int16 argc, int16 *argv) { _vm->_screen->setFont(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - _vm->_screen->printText(text); +int16 ScriptFunctions::sfDrawText(int16 argc, int16 *argv) { + + const char *text = NULL; + + if (_vm->getGameID() == GID_RTZ) { + text = _vm->_dat->getObjectString(argv[argc - 1]); + } if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + text = _vm->_dat->getString(argv[argc - 1]); + } + + if (text) { + char finalText[1024]; + switch (argc) { + case 1: + snprintf(finalText, 1024, "%s", text); + break; + case 2: + snprintf(finalText, 1024, text, argv[0]); + break; + case 3: + snprintf(finalText, 1024, text, argv[1], argv[0]); + break; + case 4: + snprintf(finalText, 1024, text, argv[2], argv[1], argv[0]); + break; + case 5: + snprintf(finalText, 1024, text, argv[3], argv[2], argv[1], argv[0]); + break; + default: + finalText[0] = '\0'; + break; + } + _vm->_screen->printText(finalText); + } + return 0; } -int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); +int16 ScriptFunctions::sfHomeText(int16 argc, int16 *argv) { + _vm->_screen->homeText(); return 0; } -int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetTextRect(int16 argc, int16 *argv) { + // Used in the save/load screens of RtZ, and perhaps other places as well int16 x1 = CLIP<int16>(argv[4], 1, 318); int16 y1 = CLIP<int16>(argv[3], 1, 198); int16 x2 = CLIP<int16>(argv[2], 1, 318); @@ -430,158 +458,179 @@ int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetTextXY(int16 argc, int16 *argv) { int16 x = CLIP<int16>(argv[1], 1, 318); int16 y = CLIP<int16>(argv[0], 1, 198); _vm->_screen->setTextXY(x, y); return 0; } -int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFontDropShadow(int16 argc, int16 *argv) { // if the drop shadow color is -1, then text drop shadow is disabled // when font drop shadow is enabled, outline is disabled _vm->_screen->setDropShadowColor(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFontColor(int16 argc, int16 *argv) { _vm->_screen->setTextColor(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFontOutline(int16 argc, int16 *argv) { // if the outline color is -1, then text outline is disabled // when font outline is enabled, drop shadow is disabled _vm->_screen->setOutlineColor(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_LOADCURSOR(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadMouseCursor(int16 argc, int16 *argv) { PictureResource *flex = _vm->_res->getPicture(argv[2]); - Graphics::Surface *surf = flex->getPicture(); - CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); - CursorMan.showMouse(true); - _vm->_res->freeResource(flex); + if (flex) { + Graphics::Surface *surf = flex->getPicture(); + CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); + _vm->_res->freeResource(flex); + } return 0; } -int16 ScriptFunctionsRtz::o1_SETGROUND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSpriteGround(int16 argc, int16 *argv) { _vm->_screen->setGround(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); +int16 ScriptFunctions::sfLoadResText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfLoadResText"); return 0; } -int16 ScriptFunctionsRtz::o1_CLIPAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLIPAREA"); +int16 ScriptFunctions::sfSetClipArea(int16 argc, int16 *argv) { + _vm->_screen->setClipArea(argv[3], argv[2], argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_SETCLIP(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSpriteClip(int16 argc, int16 *argv) { _vm->_screen->setClip(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_ISSND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfAddScreenMask(int16 argc, int16 *argv) { + _vm->_screen->drawMask(argv[2], argv[1], argv[0]); + return 0; +} + +int16 ScriptFunctions::sfSetSpriteMask(int16 argc, int16 *argv) { + _vm->_screen->setMask(argv[0]); + return 0; +} + +int16 ScriptFunctions::sfSoundPlaying(int16 argc, int16 *argv) { if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) return 1; else return 0; } -int16 ScriptFunctionsRtz::o1_STOPSND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfStopSound(int16 argc, int16 *argv) { _vm->_mixer->stopHandle(_audioStreamHandle); + _vm->_autoStopSound = false; return 0; } -int16 ScriptFunctionsRtz::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - if (!_vm->_mixer->isSoundHandleActive(_voiceStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_voiceStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } +int16 ScriptFunctions::sfPlayVoice(int16 argc, int16 *argv) { + int16 soundNum = argv[0]; + _vm->_mixer->stopHandle(_audioStreamHandle); + if (soundNum > 0) { + _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, + _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, false)); + _vm->_autoStopSound = true; } return 0; } -int16 ScriptFunctionsRtz::o1_CDPLAY(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDPLAY"); +int16 ScriptFunctions::sfPlayCd(int16 argc, int16 *argv) { + AudioCD.play(argv[0], -1, 0, 0); return 0; } -int16 ScriptFunctionsRtz::o1_STOPCD(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPCD"); - return 0; +int16 ScriptFunctions::sfStopCd(int16 argc, int16 *argv) { + if (AudioCD.isPlaying()) { + AudioCD.stop(); + return 1; + } else { + return 0; + } } -int16 ScriptFunctionsRtz::o1_CDSTATUS(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDSTATUS"); - return 0; +int16 ScriptFunctions::sfGetCdStatus(int16 argc, int16 *argv) { + return AudioCD.isPlaying() ? 1 : 0; } -int16 ScriptFunctionsRtz::o1_CDTIME(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDTIME"); +int16 ScriptFunctions::sfGetCdTime(int16 argc, int16 *argv) { + // This one is called loads of times, so it has been commented out to reduce spam + //warning("Unimplemented opcode: sfGetCdTime"); + // TODO return 0; } -int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDPLAYSEG"); +int16 ScriptFunctions::sfPlayCdSegment(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfPlayCdSegment"); return 0; } -int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); +int16 ScriptFunctions::sfPrintf(int16 argc, int16 *argv) { + const char *text = _vm->_dat->getObjectString(argv[argc - 1]); debug(4, "--> text = %s", text); return 0; } -int16 ScriptFunctionsRtz::o1_MONOCLS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MONOCLS"); +int16 ScriptFunctions::sfClearMono(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfClearMono"); return 0; } -int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetSoundEnergy(int16 argc, int16 *argv) { // This is called while in-game voices are played // Not sure what it's used for // -> It's used to animate mouths when NPCs are talking - // Commented out to reduce spam - //warning("Unimplemented opcode: o1_SNDENERGY"); - return 0; + // FIXME: This is a workaround for the "sound energy" problem + // At least the characters move their lips when talking now + return _vm->_rnd->getRandomNumber(5); } -int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLEARTEXT"); +int16 ScriptFunctions::sfClearText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfClearText"); return 1; } -int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ANIMTEXT"); +int16 ScriptFunctions::sfAnimText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfAnimText"); return 0; } -int16 ScriptFunctionsRtz::o1_TEXTWIDTH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetTextWidth(int16 argc, int16 *argv) { int16 width = 0; if (argv[1] > 0) { - Object *obj = _vm->_dat->getObject(argv[1]); - const char *text = obj->getString(); + const char *text = _vm->_dat->getObjectString(argv[1]); width = _vm->_screen->getTextWidth(argv[0], text); } return width; } -int16 ScriptFunctionsRtz::o1_PLAYMOVIE(int16 argc, int16 *argv) { - const char *movieName = _vm->_dat->getObject(argv[1])->getString(); +int16 ScriptFunctions::sfPlayMovie(int16 argc, int16 *argv) { + const char *movieName = _vm->_dat->getObjectString(argv[1]); + _vm->_system->showMouse(false); _vm->_pmvPlayer->play(movieName); + _vm->_system->showMouse(true); return 0; } -int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadSound(int16 argc, int16 *argv) { SoundResource *sound = _vm->_res->getSound(argv[0]); if (sound) { _vm->_res->freeResource(sound); @@ -590,8 +639,8 @@ int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) { - XmidiResource *xmidi = _vm->_res->getXmidi(argv[0]); +int16 ScriptFunctions::sfLoadMusic(int16 argc, int16 *argv) { + GenericResource *xmidi = _vm->_res->getXmidi(argv[0]); if (xmidi) { _vm->_res->freeResource(xmidi); return 1; @@ -599,7 +648,7 @@ int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadPicture(int16 argc, int16 *argv) { PictureResource *flex = _vm->_res->getPicture(argv[0]); if (flex) { _vm->_res->freeResource(flex); @@ -608,83 +657,92 @@ int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_MUSICVOL(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICVOL"); +int16 ScriptFunctions::sfSetMusicVolume(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfSetMusicVolume"); return 0; } -int16 ScriptFunctionsRtz::o1_RESTARTEVENTS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTARTEVENTS"); +int16 ScriptFunctions::sfRestartEvents(int16 argc, int16 *argv) { + // Used in RTZ + //warning("Unimplemented opcode: sfRestartEvents"); + // This is used to reset the event recording/queue. + // Since we don't use either it's left out. return 0; } -int16 ScriptFunctionsRtz::o1_PLACESPRITE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfPlaceSprite(int16 argc, int16 *argv) { return _vm->_screen->placeSprite(argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_PLACETEXT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfPlaceText(int16 argc, int16 *argv) { return _vm->_screen->placeText(argv[6], argv[5], argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_DELETECHANNEL(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfDeleteChannel(int16 argc, int16 *argv) { _vm->_screen->deleteChannel(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_CHANNELTYPE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetChannelType(int16 argc, int16 *argv) { return _vm->_screen->getChannelType(argv[0]); } -int16 ScriptFunctionsRtz::o1_SETSTATE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetChannelState(int16 argc, int16 *argv) { _vm->_screen->setChannelState(argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_SETLOCATION(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETLOCATION"); +int16 ScriptFunctions::sfSetChannelLocation(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfSetChannelLocation"); return 0; } -int16 ScriptFunctionsRtz::o1_SETCONTENT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETCONTENT"); +int16 ScriptFunctions::sfSetChannelContent(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfSetChannelContent"); return 0; } -int16 ScriptFunctionsRtz::o1_EXCLUDEAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_EXCLUDEAREA"); +int16 ScriptFunctions::sfSetExcludeArea(int16 argc, int16 *argv) { + _vm->_screen->setExcludeArea(argv[3], argv[2], argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_SETEXCLUDE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSpriteExclude(int16 argc, int16 *argv) { _vm->_screen->setExclude(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_GETSTATE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetChannelState(int16 argc, int16 *argv) { return _vm->_screen->getChannelState(argv[0]); } -int16 ScriptFunctionsRtz::o1_PLACEANIM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfPlaceAnim(int16 argc, int16 *argv) { return _vm->_screen->placeAnim(argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_SETFRAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetAnimFrame(int16 argc, int16 *argv) { _vm->_screen->setAnimFrame(argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_GETFRAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetAnimFrame(int16 argc, int16 *argv) { return _vm->_screen->getAnimFrame(argv[0]); } -int16 ScriptFunctionsRtz::o1_GETFRAMECOUNT(int16 argc, int16 *argv) { - debug(4, "anim = %04X\n", argv[0]); - int16 frameCount = _vm->_screen->getAnimFrameCount(argv[0]); - debug(4, "frameCount = %04X\n", frameCount); +int16 ScriptFunctions::sfGetAnimFrameCount(int16 argc, int16 *argv) { + int16 frameCount = 0; + AnimationResource *anim = _vm->_res->getAnimation(argv[0]); + if (anim) { + frameCount = anim->getCount(); + _vm->_res->freeResource(anim); + } return frameCount; } -int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetPictureWidth(int16 argc, int16 *argv) { int16 width = 0; PictureResource *flex = _vm->_res->getPicture(argv[0]); if (flex) { @@ -694,7 +752,7 @@ int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) { return width; } -int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetPictureHeight(int16 argc, int16 *argv) { int16 height = 0; PictureResource *flex = _vm->_res->getPicture(argv[0]); if (flex) { @@ -704,17 +762,16 @@ int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) { return height; } -int16 ScriptFunctionsRtz::o1_SOUNDRATE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSoundRate(int16 argc, int16 *argv) { _vm->_soundRate = argv[0]; return 1; } -int16 ScriptFunctionsRtz::o1_DRAWANIMPIC(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWANIMPIC"); - return 0; +int16 ScriptFunctions::sfDrawAnimPic(int16 argc, int16 *argv) { + return _vm->_screen->drawAnimPic(argv[5], argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadAnim(int16 argc, int16 *argv) { AnimationResource *anim = _vm->_res->getAnimation(argv[0]); if (anim) { _vm->_res->freeResource(anim); @@ -723,12 +780,13 @@ int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_READTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_READTEXT"); +int16 ScriptFunctions::sfReadText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfReadText"); return 0; } -int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfReadMenu(int16 argc, int16 *argv) { int16 objectIndex = argv[2]; int16 menuIndex = argv[1]; int16 textIndex = argv[0]; @@ -737,16 +795,17 @@ int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { if (menu) { const char *text = menu->getString(textIndex); debug(4, "objectIndex = %04X; text = %s\n", objectIndex, text); - Object *obj = _vm->_dat->getObject(objectIndex); - obj->setString(text); + _vm->_dat->setObjectString(objectIndex, text); _vm->_res->freeResource(menu); if (text) length = strlen(text); + } else { + _vm->_dat->setObjectString(objectIndex, ""); } return length; } -int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfDrawMenu(int16 argc, int16 *argv) { int16 menuIndex = argv[1]; int16 textIndex = argv[0]; MenuResource *menu = _vm->_res->getMenu(menuIndex); @@ -759,7 +818,7 @@ int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetMenuCount(int16 argc, int16 *argv) { int16 menuIndex = argv[0]; int16 count = 0; MenuResource *menu = _vm->_res->getMenu(menuIndex); @@ -770,7 +829,7 @@ int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { return count; } -int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSaveGame(int16 argc, int16 *argv) { int16 saveNum = argv[2]; int16 descObjectIndex = argv[1]; @@ -779,18 +838,13 @@ int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { if (saveNum > 999) return 6; - Object *obj = _vm->_dat->getObject(descObjectIndex); - const char *description = obj->getString(); - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->savegame(filename, description, version); + const char *description = _vm->_dat->getObjectString(descObjectIndex); + Common::String filename = _vm->getSavegameFilename(saveNum); + return _vm->_dat->savegame(filename.c_str(), description, version); } -int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadGame(int16 argc, int16 *argv) { int16 saveNum = argv[1]; int16 version = argv[0]; @@ -798,15 +852,12 @@ int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { if (saveNum > 999) return 1; - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->loadgame(filename, version); + Common::String filename = _vm->getSavegameFilename(saveNum); + return _vm->_dat->loadgame(filename.c_str(), version); } -int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetGameDescription(int16 argc, int16 *argv) { int16 descObjectIndex = argv[2]; int16 saveNum = argv[1]; @@ -816,50 +867,51 @@ int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { if (saveNum > 999) return 1; - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - Object *obj = _vm->_dat->getObject(descObjectIndex); + Common::String filename = _vm->getSavegameFilename(saveNum); - if (_vm->_dat->getSavegameDescription(filename, description)) { - obj->setString(description.c_str()); + if (_vm->_dat->getSavegameDescription(filename.c_str(), description)) { + _vm->_dat->setObjectString(descObjectIndex, description.c_str()); return 0; } else { - obj->setString(""); + _vm->_dat->setObjectString(descObjectIndex, ""); return 1; } } -int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SHAKESCREEN"); +int16 ScriptFunctions::sfShakeScreen(int16 argc, int16 *argv) { + // TODO: Used in RTZ + warning("Unimplemented opcode: sfShakeScreen"); return 0; } -int16 ScriptFunctionsRtz::o1_PLACEMENU(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLACEMENU"); +int16 ScriptFunctions::sfPlaceMenu(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfPlaceMenu"); return 0; } -int16 ScriptFunctionsRtz::o1_SETVOLUME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSoundVolume(int16 argc, int16 *argv) { _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, argv[0] * 25); _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[0] * 25); return 0; } -int16 ScriptFunctionsRtz::o1_WHATSYNTH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetSynthType(int16 argc, int16 *argv) { // 0 = Default // 1 = PCSPKR // 2 = SBFM/ADLIB // 3 = ADLIBG // 4 = MT32MPU - warning("Unimplemented opcode: o1_WHATSYNTH"); + warning("Unimplemented opcode: sfGetSynthType"); return 0; } -int16 ScriptFunctionsRtz::o1_SLOWSYSTEM(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SLOWSYSTEM"); +int16 ScriptFunctions::sfIsSlowSystem(int16 argc, int16 *argv) { + //warning("Unimplemented opcode: sfIsSlowSystem"); + // NOTE: In the original engine this value is set via a command-line parameter + // I don't think it's needed here + // One could maybe think about returning 1 here on actually slower systems. return 0; } diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h index 7e826a9f5e..9879556c3f 100644 --- a/engines/made/scriptfuncs.h +++ b/engines/made/scriptfuncs.h @@ -31,6 +31,8 @@ #include "common/func.h" #include "common/stream.h" +#include "made/resource.h" + namespace Made { class MadeEngine; @@ -40,260 +42,133 @@ typedef Common::Functor2<int16, int16*, int16> ExternalFunc; class ScriptFunctions { public: ScriptFunctions(MadeEngine *vm) : _vm(vm) {} - virtual ~ScriptFunctions() {} + virtual ~ScriptFunctions() { + for (uint i = 0; i < _externalFuncs.size(); ++i) + delete _externalFuncs[i]; + } int16 callFunction(uint16 index, int16 argc, int16 *argv) { - if (index >= _externalFuncs.size()) { - // TODO: ERROR! - return 0; - } + if (index >= _externalFuncs.size()) + error("ScriptFunctions::callFunction() Invalid function index %d", index); + debug(4, "%s", _externalFuncNames[index]); return (*_externalFuncs[index])(argc, argv); } - virtual void setupExternalsTable() = 0; + void setupExternalsTable(); + const char* getFuncName(int index) { return _externalFuncNames[index]; } + int getCount() const { return _externalFuncs.size(); } protected: MadeEngine *_vm; Audio::SoundHandle _audioStreamHandle; Audio::SoundHandle _voiceStreamHandle; Common::Array<const ExternalFunc*> _externalFuncs; + Common::Array<const char *> _externalFuncNames; + GenericResource *_musicRes; + + int16 sfSystemCall(int16 argc, int16 *argv); + int16 sfInitGraf(int16 argc, int16 *argv); + int16 sfRestoreGraf(int16 argc, int16 *argv); + int16 sfDrawPicture(int16 argc, int16 *argv); + int16 sfClearScreen(int16 argc, int16 *argv); + int16 sfShowPage(int16 argc, int16 *argv); + int16 sfPollEvent(int16 argc, int16 *argv); + int16 sfGetMouseX(int16 argc, int16 *argv); + int16 sfGetMouseY(int16 argc, int16 *argv); + int16 sfGetKey(int16 argc, int16 *argv); + int16 sfSetVisualEffect(int16 argc, int16 *argv); + int16 sfPlaySound(int16 argc, int16 *argv); + int16 sfPlayMusic(int16 argc, int16 *argv); + int16 sfStopMusic(int16 argc, int16 *argv); + int16 sfIsMusicPlaying(int16 argc, int16 *argv); + int16 sfSetTextPos(int16 argc, int16 *argv); + int16 sfFlashScreen(int16 argc, int16 *argv); + int16 sfPlayNote(int16 argc, int16 *argv); + int16 sfStopNote(int16 argc, int16 *argv); + int16 sfPlayTele(int16 argc, int16 *argv); + int16 sfStopTele(int16 argc, int16 *argv); + int16 sfHideMouseCursor(int16 argc, int16 *argv); + int16 sfShowMouseCursor(int16 argc, int16 *argv); + int16 sfGetMusicBeat(int16 argc, int16 *argv); + int16 sfSetScreenLock(int16 argc, int16 *argv); + int16 sfAddSprite(int16 argc, int16 *argv); + int16 sfFreeAnim(int16 argc, int16 *argv); + int16 sfDrawSprite(int16 argc, int16 *argv); + int16 sfEraseSprites(int16 argc, int16 *argv); + int16 sfUpdateSprites(int16 argc, int16 *argv); + int16 sfGetTimer(int16 argc, int16 *argv); + int16 sfSetTimer(int16 argc, int16 *argv); + int16 sfResetTimer(int16 argc, int16 *argv); + int16 sfAllocTimer(int16 argc, int16 *argv); + int16 sfFreeTimer(int16 argc, int16 *argv); + int16 sfSetPaletteLock(int16 argc, int16 *argv); + int16 sfSetFont(int16 argc, int16 *argv); + int16 sfDrawText(int16 argc, int16 *argv); + int16 sfHomeText(int16 argc, int16 *argv); + int16 sfSetTextRect(int16 argc, int16 *argv); + int16 sfSetTextXY(int16 argc, int16 *argv); + int16 sfSetFontDropShadow(int16 argc, int16 *argv); + int16 sfSetFontColor(int16 argc, int16 *argv); + int16 sfSetFontOutline(int16 argc, int16 *argv); + int16 sfLoadMouseCursor(int16 argc, int16 *argv); + int16 sfSetSpriteGround(int16 argc, int16 *argv); + int16 sfLoadResText(int16 argc, int16 *argv); + int16 sfSetClipArea(int16 argc, int16 *argv); + int16 sfSetSpriteClip(int16 argc, int16 *argv); + int16 sfAddScreenMask(int16 argc, int16 *argv); + int16 sfSetSpriteMask(int16 argc, int16 *argv); + int16 sfSoundPlaying(int16 argc, int16 *argv); + int16 sfStopSound(int16 argc, int16 *argv); + int16 sfPlayVoice(int16 argc, int16 *argv); + int16 sfPlayCd(int16 argc, int16 *argv); + int16 sfStopCd(int16 argc, int16 *argv); + int16 sfGetCdStatus(int16 argc, int16 *argv); + int16 sfGetCdTime(int16 argc, int16 *argv); + int16 sfPlayCdSegment(int16 argc, int16 *argv); + int16 sfPrintf(int16 argc, int16 *argv); + int16 sfClearMono(int16 argc, int16 *argv); + int16 sfGetSoundEnergy(int16 argc, int16 *argv); + int16 sfClearText(int16 argc, int16 *argv); + int16 sfAnimText(int16 argc, int16 *argv); + int16 sfGetTextWidth(int16 argc, int16 *argv); + int16 sfPlayMovie(int16 argc, int16 *argv); + int16 sfLoadSound(int16 argc, int16 *argv); + int16 sfLoadMusic(int16 argc, int16 *argv); + int16 sfLoadPicture(int16 argc, int16 *argv); + int16 sfSetMusicVolume(int16 argc, int16 *argv); + int16 sfRestartEvents(int16 argc, int16 *argv); + int16 sfPlaceSprite(int16 argc, int16 *argv); + int16 sfPlaceText(int16 argc, int16 *argv); + int16 sfDeleteChannel(int16 argc, int16 *argv); + int16 sfGetChannelType(int16 argc, int16 *argv); + int16 sfSetChannelState(int16 argc, int16 *argv); + int16 sfSetChannelLocation(int16 argc, int16 *argv); + int16 sfSetChannelContent(int16 argc, int16 *argv); + int16 sfSetExcludeArea(int16 argc, int16 *argv); + int16 sfSetSpriteExclude(int16 argc, int16 *argv); + int16 sfGetChannelState(int16 argc, int16 *argv); + int16 sfPlaceAnim(int16 argc, int16 *argv); + int16 sfSetAnimFrame(int16 argc, int16 *argv); + int16 sfGetAnimFrame(int16 argc, int16 *argv); + int16 sfGetAnimFrameCount(int16 argc, int16 *argv); + int16 sfGetPictureWidth(int16 argc, int16 *argv); + int16 sfGetPictureHeight(int16 argc, int16 *argv); + int16 sfSetSoundRate(int16 argc, int16 *argv); + int16 sfDrawAnimPic(int16 argc, int16 *argv); + int16 sfLoadAnim(int16 argc, int16 *argv); + int16 sfReadText(int16 argc, int16 *argv); + int16 sfReadMenu(int16 argc, int16 *argv); + int16 sfDrawMenu(int16 argc, int16 *argv); + int16 sfGetMenuCount(int16 argc, int16 *argv); + int16 sfSaveGame(int16 argc, int16 *argv); + int16 sfLoadGame(int16 argc, int16 *argv); + int16 sfGetGameDescription(int16 argc, int16 *argv); + int16 sfShakeScreen(int16 argc, int16 *argv); + int16 sfPlaceMenu(int16 argc, int16 *argv); + int16 sfSetSoundVolume(int16 argc, int16 *argv); + int16 sfGetSynthType(int16 argc, int16 *argv); + int16 sfIsSlowSystem(int16 argc, int16 *argv); }; -class ScriptFunctionsLgop2 : public ScriptFunctions { -public: - ScriptFunctionsLgop2(MadeEngine *vm) : ScriptFunctions(vm) {} - ~ScriptFunctionsLgop2() {} - void setupExternalsTable(); -protected: - - int16 o1_SYSTEM(int16 argc, int16 *argv); - int16 o1_INITGRAF(int16 argc, int16 *argv); - int16 o1_RESTOREGRAF(int16 argc, int16 *argv); - int16 o1_DRAWPIC(int16 argc, int16 *argv); - int16 o1_CLS(int16 argc, int16 *argv); - int16 o1_SHOWPAGE(int16 argc, int16 *argv); - int16 o1_EVENT(int16 argc, int16 *argv); - int16 o1_EVENTX(int16 argc, int16 *argv); - int16 o1_EVENTY(int16 argc, int16 *argv); - int16 o1_EVENTKEY(int16 argc, int16 *argv); - int16 o1_VISUALFX(int16 argc, int16 *argv); - int16 o1_PLAYSND(int16 argc, int16 *argv); - int16 o1_PLAYMUS(int16 argc, int16 *argv); - int16 o1_STOPMUS(int16 argc, int16 *argv); - int16 o1_ISMUS(int16 argc, int16 *argv); - int16 o1_TEXTPOS(int16 argc, int16 *argv); - int16 o1_FLASH(int16 argc, int16 *argv); - int16 o1_PLAYNOTE(int16 argc, int16 *argv); - int16 o1_STOPNOTE(int16 argc, int16 *argv); - int16 o1_PLAYTELE(int16 argc, int16 *argv); - int16 o1_STOPTELE(int16 argc, int16 *argv); - int16 o1_HIDECURS(int16 argc, int16 *argv); - int16 o1_SHOWCURS(int16 argc, int16 *argv); - int16 o1_MUSICBEAT(int16 argc, int16 *argv); - int16 o1_SCREENLOCK(int16 argc, int16 *argv); - int16 o1_ADDSPRITE(int16 argc, int16 *argv); - int16 o1_FREEANIM(int16 argc, int16 *argv); - int16 o1_DRAWSPRITE(int16 argc, int16 *argv); - int16 o1_ERASESPRITES(int16 argc, int16 *argv); - int16 o1_UPDATESPRITES(int16 argc, int16 *argv); - int16 o1_GETTIMER(int16 argc, int16 *argv); - int16 o1_SETTIMER(int16 argc, int16 *argv); - int16 o1_RESETTIMER(int16 argc, int16 *argv); - int16 o1_ALLOCTIMER(int16 argc, int16 *argv); - int16 o1_FREETIMER(int16 argc, int16 *argv); - int16 o1_PALETTELOCK(int16 argc, int16 *argv); - int16 o1_FONT(int16 argc, int16 *argv); - int16 o1_DRAWTEXT(int16 argc, int16 *argv); - int16 o1_HOMETEXT(int16 argc, int16 *argv); - int16 o1_TEXTRECT(int16 argc, int16 *argv); - int16 o1_TEXTXY(int16 argc, int16 *argv); - int16 o1_DROPSHADOW(int16 argc, int16 *argv); - int16 o1_TEXTCOLOR(int16 argc, int16 *argv); - int16 o1_OUTLINE(int16 argc, int16 *argv); - int16 o1_LOADCURSOR(int16 argc, int16 *argv); - int16 o1_SETGROUND(int16 argc, int16 *argv); - int16 o1_RESTEXT(int16 argc, int16 *argv); - int16 o1_ADDMASK(int16 argc, int16 *argv); - int16 o1_SETMASK(int16 argc, int16 *argv); - int16 o1_ISSND(int16 argc, int16 *argv); - int16 o1_STOPSND(int16 argc, int16 *argv); - int16 o1_PLAYVOICE(int16 argc, int16 *argv); -}; - -class ScriptFunctionsRtz : public ScriptFunctions { -public: - ScriptFunctionsRtz(MadeEngine *vm) : ScriptFunctions(vm) {} - ~ScriptFunctionsRtz() {} - void setupExternalsTable(); -protected: - - int16 o1_SYSTEM(int16 argc, int16 *argv); - int16 o1_INITGRAF(int16 argc, int16 *argv); - int16 o1_RESTOREGRAF(int16 argc, int16 *argv); - int16 o1_DRAWPIC(int16 argc, int16 *argv); - int16 o1_CLS(int16 argc, int16 *argv); - int16 o1_SHOWPAGE(int16 argc, int16 *argv); - int16 o1_EVENT(int16 argc, int16 *argv); - int16 o1_EVENTX(int16 argc, int16 *argv); - int16 o1_EVENTY(int16 argc, int16 *argv); - int16 o1_EVENTKEY(int16 argc, int16 *argv); - int16 o1_VISUALFX(int16 argc, int16 *argv); - int16 o1_PLAYSND(int16 argc, int16 *argv); - int16 o1_PLAYMUS(int16 argc, int16 *argv); - int16 o1_STOPMUS(int16 argc, int16 *argv); - int16 o1_ISMUS(int16 argc, int16 *argv); - int16 o1_TEXTPOS(int16 argc, int16 *argv); - int16 o1_FLASH(int16 argc, int16 *argv); - int16 o1_PLAYNOTE(int16 argc, int16 *argv); - int16 o1_STOPNOTE(int16 argc, int16 *argv); - int16 o1_PLAYTELE(int16 argc, int16 *argv); - int16 o1_STOPTELE(int16 argc, int16 *argv); - int16 o1_HIDECURS(int16 argc, int16 *argv); - int16 o1_SHOWCURS(int16 argc, int16 *argv); - int16 o1_MUSICBEAT(int16 argc, int16 *argv); - int16 o1_SCREENLOCK(int16 argc, int16 *argv); - int16 o1_ADDSPRITE(int16 argc, int16 *argv); - int16 o1_FREEANIM(int16 argc, int16 *argv); - int16 o1_DRAWSPRITE(int16 argc, int16 *argv); - int16 o1_ERASESPRITES(int16 argc, int16 *argv); - int16 o1_UPDATESPRITES(int16 argc, int16 *argv); - int16 o1_GETTIMER(int16 argc, int16 *argv); - int16 o1_SETTIMER(int16 argc, int16 *argv); - int16 o1_RESETTIMER(int16 argc, int16 *argv); - int16 o1_ALLOCTIMER(int16 argc, int16 *argv); - int16 o1_FREETIMER(int16 argc, int16 *argv); - int16 o1_PALETTELOCK(int16 argc, int16 *argv); - int16 o1_FONT(int16 argc, int16 *argv); - int16 o1_DRAWTEXT(int16 argc, int16 *argv); - int16 o1_HOMETEXT(int16 argc, int16 *argv); - int16 o1_TEXTRECT(int16 argc, int16 *argv); - int16 o1_TEXTXY(int16 argc, int16 *argv); - int16 o1_DROPSHADOW(int16 argc, int16 *argv); - int16 o1_TEXTCOLOR(int16 argc, int16 *argv); - int16 o1_OUTLINE(int16 argc, int16 *argv); - int16 o1_LOADCURSOR(int16 argc, int16 *argv); - int16 o1_SETGROUND(int16 argc, int16 *argv); - int16 o1_RESTEXT(int16 argc, int16 *argv); - int16 o1_CLIPAREA(int16 argc, int16 *argv); - int16 o1_SETCLIP(int16 argc, int16 *argv); - int16 o1_ISSND(int16 argc, int16 *argv); - int16 o1_STOPSND(int16 argc, int16 *argv); - int16 o1_PLAYVOICE(int16 argc, int16 *argv); - int16 o1_CDPLAY(int16 argc, int16 *argv); - int16 o1_STOPCD(int16 argc, int16 *argv); - int16 o1_CDSTATUS(int16 argc, int16 *argv); - int16 o1_CDTIME(int16 argc, int16 *argv); - int16 o1_CDPLAYSEG(int16 argc, int16 *argv); - int16 o1_PRINTF(int16 argc, int16 *argv); - int16 o1_MONOCLS(int16 argc, int16 *argv); - int16 o1_SNDENERGY(int16 argc, int16 *argv); - int16 o1_CLEARTEXT(int16 argc, int16 *argv); - int16 o1_ANIMTEXT(int16 argc, int16 *argv); - int16 o1_TEXTWIDTH(int16 argc, int16 *argv); - int16 o1_PLAYMOVIE(int16 argc, int16 *argv); - int16 o1_LOADSND(int16 argc, int16 *argv); - int16 o1_LOADMUS(int16 argc, int16 *argv); - int16 o1_LOADPIC(int16 argc, int16 *argv); - int16 o1_MUSICVOL(int16 argc, int16 *argv); - int16 o1_RESTARTEVENTS(int16 argc, int16 *argv); - int16 o1_PLACESPRITE(int16 argc, int16 *argv); - int16 o1_PLACETEXT(int16 argc, int16 *argv); - int16 o1_DELETECHANNEL(int16 argc, int16 *argv); - int16 o1_CHANNELTYPE(int16 argc, int16 *argv); - int16 o1_SETSTATE(int16 argc, int16 *argv); - int16 o1_SETLOCATION(int16 argc, int16 *argv); - int16 o1_SETCONTENT(int16 argc, int16 *argv); - int16 o1_EXCLUDEAREA(int16 argc, int16 *argv); - int16 o1_SETEXCLUDE(int16 argc, int16 *argv); - int16 o1_GETSTATE(int16 argc, int16 *argv); - int16 o1_PLACEANIM(int16 argc, int16 *argv); - int16 o1_SETFRAME(int16 argc, int16 *argv); - int16 o1_GETFRAME(int16 argc, int16 *argv); - int16 o1_GETFRAMECOUNT(int16 argc, int16 *argv); - int16 o1_PICWIDTH(int16 argc, int16 *argv); - int16 o1_PICHEIGHT(int16 argc, int16 *argv); - int16 o1_SOUNDRATE(int16 argc, int16 *argv); - int16 o1_DRAWANIMPIC(int16 argc, int16 *argv); - int16 o1_LOADANIM(int16 argc, int16 *argv); - int16 o1_READTEXT(int16 argc, int16 *argv); - int16 o1_READMENU(int16 argc, int16 *argv); - int16 o1_DRAWMENU(int16 argc, int16 *argv); - int16 o1_MENUCOUNT(int16 argc, int16 *argv); - int16 o1_SAVEGAME(int16 argc, int16 *argv); - int16 o1_LOADGAME(int16 argc, int16 *argv); - int16 o1_GAMENAME(int16 argc, int16 *argv); - int16 o1_SHAKESCREEN(int16 argc, int16 *argv); - int16 o1_PLACEMENU(int16 argc, int16 *argv); - int16 o1_SETVOLUME(int16 argc, int16 *argv); - int16 o1_WHATSYNTH(int16 argc, int16 *argv); - int16 o1_SLOWSYSTEM(int16 argc, int16 *argv); -}; - -class ScriptFunctionsMhne : public ScriptFunctions { -public: - ScriptFunctionsMhne(MadeEngine *vm) : ScriptFunctions(vm) {} - ~ScriptFunctionsMhne() {} - void setupExternalsTable(); -protected: - - int16 o1_SYSTEM(int16 argc, int16 *argv); - int16 o1_INITGRAF(int16 argc, int16 *argv); - int16 o1_RESTOREGRAF(int16 argc, int16 *argv); - int16 o1_DRAWPIC(int16 argc, int16 *argv); - int16 o1_CLS(int16 argc, int16 *argv); - int16 o1_SHOWPAGE(int16 argc, int16 *argv); - int16 o1_EVENT(int16 argc, int16 *argv); - int16 o1_EVENTX(int16 argc, int16 *argv); - int16 o1_EVENTY(int16 argc, int16 *argv); - int16 o1_EVENTKEY(int16 argc, int16 *argv); - int16 o1_VISUALFX(int16 argc, int16 *argv); - int16 o1_PLAYSND(int16 argc, int16 *argv); - int16 o1_PLAYMUS(int16 argc, int16 *argv); - int16 o1_STOPMUS(int16 argc, int16 *argv); - int16 o1_ISMUS(int16 argc, int16 *argv); - int16 o1_TEXTPOS(int16 argc, int16 *argv); - int16 o1_FLASH(int16 argc, int16 *argv); - int16 o1_PLAYNOTE(int16 argc, int16 *argv); - int16 o1_STOPNOTE(int16 argc, int16 *argv); - int16 o1_PLAYTELE(int16 argc, int16 *argv); - int16 o1_STOPTELE(int16 argc, int16 *argv); - int16 o1_HIDECURS(int16 argc, int16 *argv); - int16 o1_SHOWCURS(int16 argc, int16 *argv); - int16 o1_MUSICBEAT(int16 argc, int16 *argv); - int16 o1_SCREENLOCK(int16 argc, int16 *argv); - int16 o1_ADDSPRITE(int16 argc, int16 *argv); - int16 o1_FREEANIM(int16 argc, int16 *argv); - int16 o1_DRAWSPRITE(int16 argc, int16 *argv); - int16 o1_ERASESPRITES(int16 argc, int16 *argv); - int16 o1_UPDATESPRITES(int16 argc, int16 *argv); - int16 o1_GETTIMER(int16 argc, int16 *argv); - int16 o1_SETTIMER(int16 argc, int16 *argv); - int16 o1_RESETTIMER(int16 argc, int16 *argv); - int16 o1_ALLOCTIMER(int16 argc, int16 *argv); - int16 o1_FREETIMER(int16 argc, int16 *argv); - int16 o1_PALETTELOCK(int16 argc, int16 *argv); - int16 o1_FONT(int16 argc, int16 *argv); - int16 o1_DRAWTEXT(int16 argc, int16 *argv); - int16 o1_HOMETEXT(int16 argc, int16 *argv); - int16 o1_TEXTRECT(int16 argc, int16 *argv); - int16 o1_TEXTXY(int16 argc, int16 *argv); - int16 o1_DROPSHADOW(int16 argc, int16 *argv); - int16 o1_TEXTCOLOR(int16 argc, int16 *argv); - int16 o1_OUTLINE(int16 argc, int16 *argv); - int16 o1_LOADCURSOR(int16 argc, int16 *argv); - int16 o1_SETGROUND(int16 argc, int16 *argv); - int16 o1_RESTEXT(int16 argc, int16 *argv); - int16 o1_ADDMASK(int16 argc, int16 *argv); - int16 o1_SETMASK(int16 argc, int16 *argv); - int16 o1_ISSND(int16 argc, int16 *argv); - int16 o1_STOPSND(int16 argc, int16 *argv); - int16 o1_PLAYVOICE(int16 argc, int16 *argv); - int16 o1_CDPLAY(int16 argc, int16 *argv); - int16 o1_STOPCD(int16 argc, int16 *argv); - int16 o1_CDSTATUS(int16 argc, int16 *argv); - int16 o1_CDTIME(int16 argc, int16 *argv); - int16 o1_CDPLAYSEG(int16 argc, int16 *argv); -}; - } // End of namespace Made #endif /* MADE_H */ diff --git a/engines/made/scriptfuncs_lgop2.cpp b/engines/made/scriptfuncs_lgop2.cpp deleted file mode 100644 index 579492a39e..0000000000 --- a/engines/made/scriptfuncs_lgop2.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* 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 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/endian.h" -#include "common/util.h" -#include "common/events.h" - -#include "graphics/cursorman.h" - -#include "made/made.h" -#include "made/resource.h" -#include "made/database.h" -#include "made/screen.h" -#include "made/script.h" -#include "made/pmvplayer.h" -#include "made/scriptfuncs.h" -#include "made/music.h" - -namespace Made { - -/* ScriptFunctionsLgop2 */ - -typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctionsLgop2> ExternalFuncLgop2; -#define External(x) ExternalFuncLgop2(this, &ScriptFunctionsLgop2::x) -void ScriptFunctionsLgop2::setupExternalsTable() { - static const ExternalFuncLgop2 externalsTable[] = { - External(o1_SYSTEM), - External(o1_INITGRAF), - External(o1_RESTOREGRAF), - External(o1_DRAWPIC), - External(o1_CLS), - External(o1_SHOWPAGE), - External(o1_EVENT), - External(o1_EVENTX), - External(o1_EVENTY), - External(o1_EVENTKEY), - External(o1_VISUALFX), - External(o1_PLAYSND), - External(o1_PLAYMUS), - External(o1_STOPMUS), - External(o1_ISMUS), - External(o1_TEXTPOS), - External(o1_FLASH), - External(o1_PLAYNOTE), - External(o1_STOPNOTE), - External(o1_PLAYTELE), - External(o1_STOPTELE), - External(o1_HIDECURS), - External(o1_SHOWCURS), - External(o1_MUSICBEAT), - External(o1_SCREENLOCK), - External(o1_ADDSPRITE), - External(o1_FREEANIM), - External(o1_DRAWSPRITE), - External(o1_ERASESPRITES), - External(o1_UPDATESPRITES), - External(o1_GETTIMER), - External(o1_SETTIMER), - External(o1_RESETTIMER), - External(o1_ALLOCTIMER), - External(o1_FREETIMER), - External(o1_PALETTELOCK), - External(o1_FONT), - External(o1_DRAWTEXT), - External(o1_HOMETEXT), - External(o1_TEXTRECT), - External(o1_TEXTXY), - External(o1_DROPSHADOW), - External(o1_TEXTCOLOR), - External(o1_OUTLINE), - External(o1_LOADCURSOR), - External(o1_SETGROUND), - External(o1_RESTEXT), - External(o1_ADDMASK), - External(o1_SETMASK), - External(o1_ISSND), - External(o1_STOPSND), - External(o1_PLAYVOICE) - }; - - for (int i = 0; i < ARRAYSIZE(externalsTable); ++i) - _externalFuncs.push_back(&externalsTable[i]); - -} -#undef External - -int16 ScriptFunctionsLgop2::o1_SYSTEM(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_INITGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_RESTOREGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DRAWPIC(int16 argc, int16 *argv) { - return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsLgop2::o1_CLS(int16 argc, int16 *argv) { - _vm->_screen->clearScreen(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SHOWPAGE(int16 argc, int16 *argv) { - _vm->_screen->show(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_EVENT(int16 argc, int16 *argv) { - - Common::Event event; - Common::EventManager *eventMan = g_system->getEventManager(); - - int16 eventNum = 0; - - if (eventMan->pollEvent(event)) { - switch (event.type) { - - case Common::EVENT_MOUSEMOVE: - _vm->_eventMouseX = event.mouse.x; - _vm->_eventMouseY = event.mouse.y; - break; - - case Common::EVENT_LBUTTONDOWN: - eventNum = 1; - break; - - /* - case Common::EVENT_LBUTTONUP: - eventNum = 2; // TODO: Is this correct? - break; - */ - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - /* - case Common::EVENT_RBUTTONUP: - eventNum = 4; // TODO: Is this correct? - break; - */ - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } - - _vm->_system->updateScreen(); - - return eventNum; -} - -int16 ScriptFunctionsLgop2::o1_EVENTX(int16 argc, int16 *argv) { - return _vm->_eventMouseX; -} - -int16 ScriptFunctionsLgop2::o1_EVENTY(int16 argc, int16 *argv) { - return _vm->_eventMouseY; -} - -int16 ScriptFunctionsLgop2::o1_EVENTKEY(int16 argc, int16 *argv) { - return _vm->_eventKey; -} - -int16 ScriptFunctionsLgop2::o1_VISUALFX(int16 argc, int16 *argv) { - _vm->_screen->setVisualEffectNum(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - - if (argc > 1) { - soundNum = argv[1]; - loop = (argv[0] == 1); - } - - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } - } - - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYMUS(int16 argc, int16 *argv) { - /* - - Disabled for now since MIDI player doesn't support all commands - which results in strange behavior. - - int16 musicNum = argv[0]; - if (musicNum > 0) { - GenericResource *midi = _vm->_res->getMidi(musicNum); - _vm->_music->playSMF(midi); - _vm->_res->freeResource(midi); - } - */ - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ISMUS(int16 argc, int16 *argv) { - if (_vm->_music->isPlaying()) - return 1; - else - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); - // This seems to be some kind of low-level opcode. - // The original engine calls int 10h to set the VGA cursor position. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_FLASH(int16 argc, int16 *argv) { - _vm->_screen->flash(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_HIDECURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(false); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SHOWCURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(true); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SCREENLOCK(int16 argc, int16 *argv) { - _vm->_screen->setScreenLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ADDSPRITE(int16 argc, int16 *argv) { - //_vm->_screen->drawSprite(argv[2], argv[1], argv[0]); - return argv[2]; -} - -int16 ScriptFunctionsLgop2::o1_FREEANIM(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DRAWSPRITE(int16 argc, int16 *argv) { - return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsLgop2::o1_ERASESPRITES(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_UPDATESPRITES(int16 argc, int16 *argv) { - _vm->_screen->updateSprites(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_GETTIMER(int16 argc, int16 *argv) { - return _vm->getTimer(argv[0]); -} - -int16 ScriptFunctionsLgop2::o1_SETTIMER(int16 argc, int16 *argv) { - _vm->setTimer(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_RESETTIMER(int16 argc, int16 *argv) { - _vm->resetTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ALLOCTIMER(int16 argc, int16 *argv) { - int16 timerNum = _vm->allocTimer(); - return timerNum; -} - -int16 ScriptFunctionsLgop2::o1_FREETIMER(int16 argc, int16 *argv) { - _vm->freeTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PALETTELOCK(int16 argc, int16 *argv) { - _vm->_screen->setPaletteLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_FONT(int16 argc, int16 *argv) { - _vm->_screen->setFont(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DRAWTEXT(int16 argc, int16 *argv) { - // TODO: Needs vsprintf to get the correct text - const char *text = _vm->_dat->getString(argv[argc - 1]); - _vm->_screen->printText(text); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTRECT(int16 argc, int16 *argv) { - int16 x1 = CLIP<int16>(argv[4], 1, 318); - int16 y1 = CLIP<int16>(argv[3], 1, 198); - int16 x2 = CLIP<int16>(argv[2], 1, 318); - int16 y2 = CLIP<int16>(argv[1], 1, 198); - //int16 textValue = argv[0]; - // TODO: textValue - _vm->_screen->setTextRect(Common::Rect(x1, y1, x2, y2)); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTXY(int16 argc, int16 *argv) { - int16 x = CLIP<int16>(argv[1], 1, 318); - int16 y = CLIP<int16>(argv[0], 1, 198); - _vm->_screen->setTextXY(x, y); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DROPSHADOW(int16 argc, int16 *argv) { - // if the drop shadow color is -1, then text drop shadow is disabled - // when font drop shadow is enabled, outline is disabled - _vm->_screen->setDropShadowColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTCOLOR(int16 argc, int16 *argv) { - _vm->_screen->setTextColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_OUTLINE(int16 argc, int16 *argv) { - // if the outline color is -1, then text outline is disabled - // when font outline is enabled, drop shadow is disabled - _vm->_screen->setOutlineColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_LOADCURSOR(int16 argc, int16 *argv) { - PictureResource *flex = _vm->_res->getPicture(argv[2]); - Graphics::Surface *surf = flex->getPicture(); - CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); - CursorMan.showMouse(true); - _vm->_res->freeResource(flex); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SETGROUND(int16 argc, int16 *argv) { - _vm->_screen->setGround(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ADDMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ADDMASK"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SETMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETMASK"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ISSND(int16 argc, int16 *argv) { - if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) - return 1; - else - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPSND(int16 argc, int16 *argv) { - _vm->_mixer->stopHandle(_audioStreamHandle); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - _vm->_mixer->stopHandle(_audioStreamHandle); - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } - return 0; -} - -} // End of namespace Made diff --git a/engines/made/scriptfuncs_mhne.cpp b/engines/made/scriptfuncs_mhne.cpp deleted file mode 100644 index 65e9c6e070..0000000000 --- a/engines/made/scriptfuncs_mhne.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* 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 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/endian.h" -#include "common/util.h" -#include "common/events.h" - -#include "graphics/cursorman.h" - -#include "made/made.h" -#include "made/resource.h" -#include "made/database.h" -#include "made/screen.h" -#include "made/script.h" -#include "made/pmvplayer.h" -#include "made/scriptfuncs.h" -#include "made/music.h" - -namespace Made { - -/* ScriptFunctionsMhne */ - -typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctionsMhne> ExternalFuncMhne; -#define External(x) ExternalFuncMhne(this, &ScriptFunctionsMhne::x) -void ScriptFunctionsMhne::setupExternalsTable() { - static const ExternalFuncMhne externalsTable[] = { - External(o1_SYSTEM), - External(o1_INITGRAF), - External(o1_RESTOREGRAF), - External(o1_DRAWPIC), - External(o1_CLS), - External(o1_SHOWPAGE), - External(o1_EVENT), - External(o1_EVENTX), - External(o1_EVENTY), - External(o1_EVENTKEY), - External(o1_VISUALFX), - External(o1_PLAYSND), - External(o1_PLAYMUS), - External(o1_STOPMUS), - External(o1_ISMUS), - External(o1_TEXTPOS), - External(o1_FLASH), - External(o1_PLAYNOTE), - External(o1_STOPNOTE), - External(o1_PLAYTELE), - External(o1_STOPTELE), - External(o1_HIDECURS), - External(o1_SHOWCURS), - External(o1_MUSICBEAT), - External(o1_SCREENLOCK), - External(o1_ADDSPRITE), - External(o1_FREEANIM), - External(o1_DRAWSPRITE), - External(o1_ERASESPRITES), - External(o1_UPDATESPRITES), - External(o1_GETTIMER), - External(o1_SETTIMER), - External(o1_RESETTIMER), - External(o1_ALLOCTIMER), - External(o1_FREETIMER), - External(o1_PALETTELOCK), - External(o1_FONT), - External(o1_DRAWTEXT), - External(o1_HOMETEXT), - External(o1_TEXTRECT), - External(o1_TEXTXY), - External(o1_DROPSHADOW), - External(o1_TEXTCOLOR), - External(o1_OUTLINE), - External(o1_LOADCURSOR), - External(o1_SETGROUND), - External(o1_RESTEXT), - External(o1_ADDMASK), - External(o1_SETMASK), - External(o1_ISSND), - External(o1_STOPSND), - External(o1_PLAYVOICE), - External(o1_CDPLAY), - External(o1_STOPCD), - External(o1_CDSTATUS), - External(o1_CDTIME), - External(o1_CDPLAYSEG), - }; - - for (int i = 0; i < ARRAYSIZE(externalsTable); ++i) - _externalFuncs.push_back(&externalsTable[i]); - -} -#undef External - -int16 ScriptFunctionsMhne::o1_SYSTEM(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsMhne::o1_INITGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsMhne::o1_RESTOREGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsMhne::o1_DRAWPIC(int16 argc, int16 *argv) { - return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsMhne::o1_CLS(int16 argc, int16 *argv) { - _vm->_screen->clearScreen(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SHOWPAGE(int16 argc, int16 *argv) { - _vm->_screen->show(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_EVENT(int16 argc, int16 *argv) { - - Common::Event event; - Common::EventManager *eventMan = g_system->getEventManager(); - - int16 eventNum = 0; - - if (eventMan->pollEvent(event)) { - switch (event.type) { - - case Common::EVENT_MOUSEMOVE: - _vm->_eventMouseX = event.mouse.x; - _vm->_eventMouseY = event.mouse.y; - break; - - case Common::EVENT_LBUTTONDOWN: - eventNum = 1; - break; - - /* - case Common::EVENT_LBUTTONUP: - eventNum = 2; // TODO: Is this correct? - break; - */ - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - /* - case Common::EVENT_RBUTTONUP: - eventNum = 4; // TODO: Is this correct? - break; - */ - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } - - _vm->_system->updateScreen(); - - return eventNum; -} - -int16 ScriptFunctionsMhne::o1_EVENTX(int16 argc, int16 *argv) { - return _vm->_eventMouseX; -} - -int16 ScriptFunctionsMhne::o1_EVENTY(int16 argc, int16 *argv) { - return _vm->_eventMouseY; -} - -int16 ScriptFunctionsMhne::o1_EVENTKEY(int16 argc, int16 *argv) { - return _vm->_eventKey; -} - -int16 ScriptFunctionsMhne::o1_VISUALFX(int16 argc, int16 *argv) { - _vm->_screen->setVisualEffectNum(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - - if (argc > 1) { - soundNum = argv[1]; - loop = (argv[0] == 1); - } - - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } - } - - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYMUS(int16 argc, int16 *argv) { - int16 musicNum = argv[0]; - if (musicNum > 0) { - GenericResource *xmidi = _vm->_res->getXmidi(musicNum); - _vm->_music->playXMIDI(xmidi); - _vm->_res->freeResource(xmidi); - } - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ISMUS(int16 argc, int16 *argv) { - if (_vm->_music->isPlaying()) - return 1; - else - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); - // This seems to be some kind of low-level opcode. - // The original engine calls int 10h to set the VGA cursor position. - return 0; -} - -int16 ScriptFunctionsMhne::o1_FLASH(int16 argc, int16 *argv) { - _vm->_screen->flash(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_HIDECURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(false); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SHOWCURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(true); - return 0; -} - -int16 ScriptFunctionsMhne::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SCREENLOCK(int16 argc, int16 *argv) { - _vm->_screen->setScreenLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ADDSPRITE(int16 argc, int16 *argv) { - //_vm->_screen->drawSprite(argv[2], argv[1], argv[0]); - return argv[2]; -} - -int16 ScriptFunctionsMhne::o1_FREEANIM(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_DRAWSPRITE(int16 argc, int16 *argv) { - return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsMhne::o1_ERASESPRITES(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_UPDATESPRITES(int16 argc, int16 *argv) { - _vm->_screen->updateSprites(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_GETTIMER(int16 argc, int16 *argv) { - return _vm->getTimer(argv[0]); -} - -int16 ScriptFunctionsMhne::o1_SETTIMER(int16 argc, int16 *argv) { - _vm->setTimer(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_RESETTIMER(int16 argc, int16 *argv) { - _vm->resetTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ALLOCTIMER(int16 argc, int16 *argv) { - int16 timerNum = _vm->allocTimer(); - return timerNum; -} - -int16 ScriptFunctionsMhne::o1_FREETIMER(int16 argc, int16 *argv) { - _vm->freeTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PALETTELOCK(int16 argc, int16 *argv) { - _vm->_screen->setPaletteLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsMhne::o1_FONT(int16 argc, int16 *argv) { - _vm->_screen->setFont(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_DRAWTEXT(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - _vm->_screen->printText(text); - return 0; -} - -int16 ScriptFunctionsMhne::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTRECT(int16 argc, int16 *argv) { - int16 x1 = CLIP<int16>(argv[4], 1, 318); - int16 y1 = CLIP<int16>(argv[3], 1, 198); - int16 x2 = CLIP<int16>(argv[2], 1, 318); - int16 y2 = CLIP<int16>(argv[1], 1, 198); - //int16 textValue = argv[0]; - // TODO: textValue - _vm->_screen->setTextRect(Common::Rect(x1, y1, x2, y2)); - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTXY(int16 argc, int16 *argv) { - int16 x = CLIP<int16>(argv[1], 1, 318); - int16 y = CLIP<int16>(argv[0], 1, 198); - _vm->_screen->setTextXY(x, y); - return 0; -} - -int16 ScriptFunctionsMhne::o1_DROPSHADOW(int16 argc, int16 *argv) { - // if the drop shadow color is -1, then text drop shadow is disabled - // when font drop shadow is enabled, outline is disabled - _vm->_screen->setDropShadowColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTCOLOR(int16 argc, int16 *argv) { - _vm->_screen->setTextColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_OUTLINE(int16 argc, int16 *argv) { - // if the outline color is -1, then text outline is disabled - // when font outline is enabled, drop shadow is disabled - _vm->_screen->setOutlineColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_LOADCURSOR(int16 argc, int16 *argv) { - PictureResource *flex = _vm->_res->getPicture(argv[2]); - Graphics::Surface *surf = flex->getPicture(); - CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); - CursorMan.showMouse(true); - _vm->_res->freeResource(flex); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SETGROUND(int16 argc, int16 *argv) { - _vm->_screen->setGround(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ADDMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ADDMASK"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SETMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETMASK"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ISSND(int16 argc, int16 *argv) { - if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) - return 1; - else - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPSND(int16 argc, int16 *argv) { - _vm->_mixer->stopHandle(_audioStreamHandle); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - _vm->_mixer->stopHandle(_audioStreamHandle); - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDPLAY(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDPLAY"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPCD(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPCD"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDSTATUS(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDSTATUS"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDTIME(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDTIME"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDPLAYSEG(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDPLAYSEG"); - return 0; -} - -} // End of namespace Made diff --git a/engines/made/scriptfuncs_rtz.cpp b/engines/made/scriptfuncs_rtz.cpp deleted file mode 100644 index 1186a88de8..0000000000 --- a/engines/made/scriptfuncs_rtz.cpp +++ /dev/null @@ -1,864 +0,0 @@ -/* 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 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/endian.h" -#include "common/util.h" -#include "common/events.h" - -#include "graphics/cursorman.h" - -#include "made/made.h" -#include "made/resource.h" -#include "made/database.h" -#include "made/screen.h" -#include "made/script.h" -#include "made/pmvplayer.h" -#include "made/scriptfuncs.h" -#include "made/music.h" - -namespace Made { - -/* ScriptFunctionsRtz */ - -typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctionsRtz> ExternalFuncRtz; -#define External(x) ExternalFuncRtz(this, &ScriptFunctionsRtz::x) -void ScriptFunctionsRtz::setupExternalsTable() { - static const ExternalFuncRtz externalsTable[] = { - External(o1_SYSTEM), - External(o1_INITGRAF), - External(o1_RESTOREGRAF), - External(o1_DRAWPIC), - External(o1_CLS), - External(o1_SHOWPAGE), - External(o1_EVENT), - External(o1_EVENTX), - External(o1_EVENTY), - External(o1_EVENTKEY), - External(o1_VISUALFX), - External(o1_PLAYSND), - External(o1_PLAYMUS), - External(o1_STOPMUS), - External(o1_ISMUS), - External(o1_TEXTPOS), - External(o1_FLASH), - External(o1_PLAYNOTE), - External(o1_STOPNOTE), - External(o1_PLAYTELE), - External(o1_STOPTELE), - External(o1_HIDECURS), - External(o1_SHOWCURS), - External(o1_MUSICBEAT), - External(o1_SCREENLOCK), - External(o1_ADDSPRITE), - External(o1_FREEANIM), - External(o1_DRAWSPRITE), - External(o1_ERASESPRITES), - External(o1_UPDATESPRITES), - External(o1_GETTIMER), - External(o1_SETTIMER), - External(o1_RESETTIMER), - External(o1_ALLOCTIMER), - External(o1_FREETIMER), - External(o1_PALETTELOCK), - External(o1_FONT), - External(o1_DRAWTEXT), - External(o1_HOMETEXT), - External(o1_TEXTRECT), - External(o1_TEXTXY), - External(o1_DROPSHADOW), - External(o1_TEXTCOLOR), - External(o1_OUTLINE), - External(o1_LOADCURSOR), - External(o1_SETGROUND), - External(o1_RESTEXT), - External(o1_CLIPAREA), - External(o1_SETCLIP), - External(o1_ISSND), - External(o1_STOPSND), - External(o1_PLAYVOICE), - External(o1_CDPLAY), - External(o1_STOPCD), - External(o1_CDSTATUS), - External(o1_CDTIME), - External(o1_CDPLAYSEG), - External(o1_PRINTF), - External(o1_MONOCLS), - External(o1_SNDENERGY), - External(o1_CLEARTEXT), - External(o1_ANIMTEXT), - External(o1_TEXTWIDTH), - External(o1_PLAYMOVIE), - External(o1_LOADSND), - External(o1_LOADMUS), - External(o1_LOADPIC), - External(o1_MUSICVOL), - External(o1_RESTARTEVENTS), - External(o1_PLACESPRITE), - External(o1_PLACETEXT), - External(o1_DELETECHANNEL), - External(o1_CHANNELTYPE), - External(o1_SETSTATE), - External(o1_SETLOCATION), - External(o1_SETCONTENT), - External(o1_EXCLUDEAREA), - External(o1_SETEXCLUDE), - External(o1_GETSTATE), - External(o1_PLACEANIM), - External(o1_SETFRAME), - External(o1_GETFRAME), - External(o1_GETFRAMECOUNT), - External(o1_PICWIDTH), - External(o1_PICHEIGHT), - External(o1_SOUNDRATE), - External(o1_DRAWANIMPIC), - External(o1_LOADANIM), - External(o1_READTEXT), - External(o1_READMENU), - External(o1_DRAWMENU), - External(o1_MENUCOUNT), - External(o1_SAVEGAME), - External(o1_LOADGAME), - External(o1_GAMENAME), - External(o1_SHAKESCREEN), - External(o1_PLACEMENU), - External(o1_SETVOLUME), - External(o1_WHATSYNTH), - External(o1_SLOWSYSTEM) - }; - - for (int i = 0; i < ARRAYSIZE(externalsTable); ++i) - _externalFuncs.push_back(&externalsTable[i]); - -} -#undef External - -int16 ScriptFunctionsRtz::o1_SYSTEM(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsRtz::o1_INITGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESTOREGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsRtz::o1_DRAWPIC(int16 argc, int16 *argv) { - return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsRtz::o1_CLS(int16 argc, int16 *argv) { - _vm->_screen->clearScreen(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SHOWPAGE(int16 argc, int16 *argv) { - _vm->_screen->show(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_EVENT(int16 argc, int16 *argv) { - - Common::Event event; - Common::EventManager *eventMan = g_system->getEventManager(); - - int16 eventNum = 0; - - if (eventMan->pollEvent(event)) { - switch (event.type) { - - case Common::EVENT_MOUSEMOVE: - _vm->_eventMouseX = event.mouse.x; - _vm->_eventMouseY = event.mouse.y; - break; - - case Common::EVENT_LBUTTONDOWN: - eventNum = 1; - break; - - /* - case Common::EVENT_LBUTTONUP: - eventNum = 2; // TODO: Is this correct? - break; - */ - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - /* - case Common::EVENT_RBUTTONUP: - eventNum = 4; // TODO: Is this correct? - break; - */ - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } - - _vm->_system->updateScreen(); - - return eventNum; -} - -int16 ScriptFunctionsRtz::o1_EVENTX(int16 argc, int16 *argv) { - return _vm->_eventMouseX; -} - -int16 ScriptFunctionsRtz::o1_EVENTY(int16 argc, int16 *argv) { - return _vm->_eventMouseY; -} - -int16 ScriptFunctionsRtz::o1_EVENTKEY(int16 argc, int16 *argv) { - return _vm->_eventKey; -} - -int16 ScriptFunctionsRtz::o1_VISUALFX(int16 argc, int16 *argv) { - _vm->_screen->setVisualEffectNum(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - - if (argc > 1) { - soundNum = argv[1]; - loop = (argv[0] == 1); - } - - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } - } - - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYMUS(int16 argc, int16 *argv) { - int16 musicNum = argv[0]; - if (musicNum > 0) { - GenericResource *xmidi = _vm->_res->getXmidi(musicNum); - _vm->_music->playXMIDI(xmidi); - _vm->_res->freeResource(xmidi); - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ISMUS(int16 argc, int16 *argv) { - if (_vm->_music->isPlaying()) - return 1; - else - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); - // This seems to be some kind of low-level opcode. - // The original engine calls int 10h to set the VGA cursor position. - return 0; -} - -int16 ScriptFunctionsRtz::o1_FLASH(int16 argc, int16 *argv) { - _vm->_screen->flash(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_HIDECURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(false); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SHOWCURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(true); - return 0; -} - -int16 ScriptFunctionsRtz::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SCREENLOCK(int16 argc, int16 *argv) { - _vm->_screen->setScreenLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ADDSPRITE(int16 argc, int16 *argv) { - //_vm->_screen->drawSprite(argv[2], argv[1], argv[0]); - return 0;//argv[2]; -} - -int16 ScriptFunctionsRtz::o1_FREEANIM(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_DRAWSPRITE(int16 argc, int16 *argv) { - return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsRtz::o1_ERASESPRITES(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_UPDATESPRITES(int16 argc, int16 *argv) { - _vm->_screen->updateSprites(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_GETTIMER(int16 argc, int16 *argv) { - return _vm->getTimer(argv[0]); -} - -int16 ScriptFunctionsRtz::o1_SETTIMER(int16 argc, int16 *argv) { - _vm->setTimer(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESETTIMER(int16 argc, int16 *argv) { - _vm->resetTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ALLOCTIMER(int16 argc, int16 *argv) { - int16 timerNum = _vm->allocTimer(); - return timerNum; -} - -int16 ScriptFunctionsRtz::o1_FREETIMER(int16 argc, int16 *argv) { - _vm->freeTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PALETTELOCK(int16 argc, int16 *argv) { - _vm->_screen->setPaletteLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) { - _vm->_screen->setFont(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) { - // TODO: Needs vsprintf to get the correct text - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - _vm->_screen->printText(text); - return 0; -} - -int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { - int16 x1 = CLIP<int16>(argv[4], 1, 318); - int16 y1 = CLIP<int16>(argv[3], 1, 198); - int16 x2 = CLIP<int16>(argv[2], 1, 318); - int16 y2 = CLIP<int16>(argv[1], 1, 198); - //int16 textValue = argv[0]; - // TODO: textValue - _vm->_screen->setTextRect(Common::Rect(x1, y1, x2, y2)); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) { - int16 x = CLIP<int16>(argv[1], 1, 318); - int16 y = CLIP<int16>(argv[0], 1, 198); - _vm->_screen->setTextXY(x, y); - return 0; -} - -int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) { - // if the drop shadow color is -1, then text drop shadow is disabled - // when font drop shadow is enabled, outline is disabled - _vm->_screen->setDropShadowColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) { - _vm->_screen->setTextColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) { - // if the outline color is -1, then text outline is disabled - // when font outline is enabled, drop shadow is disabled - _vm->_screen->setOutlineColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADCURSOR(int16 argc, int16 *argv) { - PictureResource *flex = _vm->_res->getPicture(argv[2]); - Graphics::Surface *surf = flex->getPicture(); - CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); - CursorMan.showMouse(true); - _vm->_res->freeResource(flex); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETGROUND(int16 argc, int16 *argv) { - _vm->_screen->setGround(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CLIPAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLIPAREA"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETCLIP(int16 argc, int16 *argv) { - _vm->_screen->setClip(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ISSND(int16 argc, int16 *argv) { - if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) - return 1; - else - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPSND(int16 argc, int16 *argv) { - _vm->_mixer->stopHandle(_audioStreamHandle); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - _vm->_mixer->stopHandle(_audioStreamHandle); - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDPLAY(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDPLAY"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPCD(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPCD"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDSTATUS(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDSTATUS"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDTIME(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDTIME"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDPLAYSEG"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - debug(4, "--> text = %s", text); - return 0; -} - -int16 ScriptFunctionsRtz::o1_MONOCLS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MONOCLS"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) { - // This is called while in-game voices are played - // Not sure what it's used for - // -> It's used to animate mouths when NPCs are talking - // Commented out to reduce spam - //warning("Unimplemented opcode: o1_SNDENERGY"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLEARTEXT"); - return 1; -} - -int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ANIMTEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTWIDTH(int16 argc, int16 *argv) { - int16 width = 0; - if (argv[1] > 0) { - Object *obj = _vm->_dat->getObject(argv[1]); - const char *text = obj->getString(); - width = _vm->_screen->getTextWidth(argv[0], text); - } - return width; -} - -int16 ScriptFunctionsRtz::o1_PLAYMOVIE(int16 argc, int16 *argv) { - const char *movieName = _vm->_dat->getObject(argv[1])->getString(); - _vm->_pmvPlayer->play(movieName); - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) { - SoundResource *sound = _vm->_res->getSound(argv[0]); - if (sound) { - _vm->_res->freeResource(sound); - return 1; - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) { - GenericResource *xmidi = _vm->_res->getXmidi(argv[0]); - if (xmidi) { - _vm->_res->freeResource(xmidi); - return 1; - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) { - PictureResource *flex = _vm->_res->getPicture(argv[0]); - if (flex) { - _vm->_res->freeResource(flex); - return 1; - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_MUSICVOL(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICVOL"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESTARTEVENTS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTARTEVENTS"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLACESPRITE(int16 argc, int16 *argv) { - return _vm->_screen->placeSprite(argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsRtz::o1_PLACETEXT(int16 argc, int16 *argv) { - return _vm->_screen->placeText(argv[6], argv[5], argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsRtz::o1_DELETECHANNEL(int16 argc, int16 *argv) { - _vm->_screen->deleteChannel(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CHANNELTYPE(int16 argc, int16 *argv) { - return _vm->_screen->getChannelType(argv[0]); -} - -int16 ScriptFunctionsRtz::o1_SETSTATE(int16 argc, int16 *argv) { - _vm->_screen->setChannelState(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETLOCATION(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETLOCATION"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETCONTENT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETCONTENT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_EXCLUDEAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_EXCLUDEAREA"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETEXCLUDE(int16 argc, int16 *argv) { - _vm->_screen->setExclude(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_GETSTATE(int16 argc, int16 *argv) { - return _vm->_screen->getChannelState(argv[0]); -} - -int16 ScriptFunctionsRtz::o1_PLACEANIM(int16 argc, int16 *argv) { - return _vm->_screen->placeAnim(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsRtz::o1_SETFRAME(int16 argc, int16 *argv) { - _vm->_screen->setAnimFrame(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_GETFRAME(int16 argc, int16 *argv) { - return _vm->_screen->getAnimFrame(argv[0]); -} - -int16 ScriptFunctionsRtz::o1_GETFRAMECOUNT(int16 argc, int16 *argv) { - return _vm->_screen->getAnimFrameCount(argv[0]); -} - -int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) { - int16 width = 0; - PictureResource *flex = _vm->_res->getPicture(argv[0]); - if (flex) { - width = flex->getPicture()->w; - _vm->_res->freeResource(flex); - } - return width; -} - -int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) { - int16 height = 0; - PictureResource *flex = _vm->_res->getPicture(argv[0]); - if (flex) { - height = flex->getPicture()->h; - _vm->_res->freeResource(flex); - } - return height; -} - -int16 ScriptFunctionsRtz::o1_SOUNDRATE(int16 argc, int16 *argv) { - _vm->_soundRate = argv[0]; - return 1; -} - -int16 ScriptFunctionsRtz::o1_DRAWANIMPIC(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWANIMPIC"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) { - AnimationResource *anim = _vm->_res->getAnimation(argv[0]); - if (anim) { - _vm->_res->freeResource(anim); - return 1; - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_READTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_READTEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { - int16 objectIndex = argv[2]; - int16 menuIndex = argv[1]; - int16 textIndex = argv[0]; - int16 length = 0; - MenuResource *menu = _vm->_res->getMenu(menuIndex); - if (menu) { - const char *text = menu->getString(textIndex); - debug(4, "objectIndex = %04X; text = %s\n", objectIndex, text); - Object *obj = _vm->_dat->getObject(objectIndex); - obj->setString(text); - _vm->_res->freeResource(menu); - if (text) - length = strlen(text); - } - return length; -} - -int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { - int16 menuIndex = argv[1]; - int16 textIndex = argv[0]; - MenuResource *menu = _vm->_res->getMenu(menuIndex); - if (menu) { - const char *text = menu->getString(textIndex); - if (text) - _vm->_screen->printText(text); - _vm->_res->freeResource(menu); - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { - int16 menuIndex = argv[0]; - int16 count = 0; - MenuResource *menu = _vm->_res->getMenu(menuIndex); - if (menu) { - count = menu->getCount(); - _vm->_res->freeResource(menu); - } - return count; -} - -int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { - - int16 saveNum = argv[2]; - int16 descObjectIndex = argv[1]; - int16 version = argv[0]; - - if (saveNum > 999) - return 6; - - Object *obj = _vm->_dat->getObject(descObjectIndex); - const char *description = obj->getString(); - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->savegame(filename, description, version); - -} - -int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { - - int16 saveNum = argv[1]; - int16 version = argv[0]; - - if (saveNum > 999) - return 1; - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->loadgame(filename, version); - -} - -int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { - - int16 descObjectIndex = argv[2]; - int16 saveNum = argv[1]; - /*int16 version = argv[0];*/ - Common::String description; - - if (saveNum > 999) - return 1; - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - Object *obj = _vm->_dat->getObject(descObjectIndex); - - if (_vm->_dat->getSavegameDescription(filename, description)) { - obj->setString(description.c_str()); - return 0; - } else { - obj->setString(""); - return 1; - } - -} - -int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SHAKESCREEN"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLACEMENU(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLACEMENU"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETVOLUME(int16 argc, int16 *argv) { - _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, argv[0] * 25); - _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[0] * 25); - return 0; -} - -int16 ScriptFunctionsRtz::o1_WHATSYNTH(int16 argc, int16 *argv) { - // 0 = Default - // 1 = PCSPKR - // 2 = SBFM/ADLIB - // 3 = ADLIBG - // 4 = MT32MPU - warning("Unimplemented opcode: o1_WHATSYNTH"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SLOWSYSTEM(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SLOWSYSTEM"); - return 0; -} - -} // End of namespace Made diff --git a/engines/metaengine.h b/engines/metaengine.h index 5db791a1b7..aef860e0f9 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -93,4 +93,25 @@ public: } }; + +// Engine plugins + +typedef PluginSubclass<MetaEngine> EnginePlugin; + +/** + * Singleton class which manages all Engine plugins. + */ +class EngineManager : public Common::Singleton<EngineManager> { +private: + friend class Common::Singleton<SingletonBaseType>; + +public: + GameDescriptor findGame(const Common::String &gameName, const EnginePlugin **plugin = NULL) const; + GameList detectGames(const FSList &fslist) const; + const EnginePlugin::List &getPlugins() const; +}; + +/** Convenience shortcut for accessing the engine manager. */ +#define EngineMan EngineManager::instance() + #endif diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index c9a547d75b..68e6a70ffb 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -30,6 +30,7 @@ #include "graphics/primitives.h" // for Graphics::drawLine +#include "parallaction/input.h" #include "parallaction/parallaction.h" #include "parallaction/sound.h" @@ -303,14 +304,14 @@ void Parallaction_ns::_c_trasformata(void *parm) { } void Parallaction_ns::_c_offMouse(void *parm) { - showCursor(false); + _input->showCursor(false); _engineFlags |= kEngineBlockInput; return; } void Parallaction_ns::_c_onMouse(void *parm) { _engineFlags &= ~kEngineBlockInput; - showCursor(true); + _input->showCursor(true); return; } @@ -339,7 +340,7 @@ void Parallaction_ns::_c_endComment(void *param) { g_system->delayMillis(20); } - waitUntilLeftClick(); + _input->waitUntilLeftClick(); _gfx->freeBalloons(); return; @@ -395,7 +396,7 @@ void Parallaction_ns::_c_finito(void *parm) { _gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 100); _gfx->showLabel(id[2], CENTER_LABEL_HORIZONTAL, 130); _gfx->showLabel(id[3], CENTER_LABEL_HORIZONTAL, 160); - waitUntilLeftClick(); + _input->waitUntilLeftClick(); _gfx->freeLabels(); @@ -422,8 +423,8 @@ void Parallaction_ns::_c_testResult(void *parm) { parseLocation("common"); uint id[2]; - id[0] = _gfx->createLabel(_menuFont, _slideText[0], 1); - id[1] = _gfx->createLabel(_menuFont, _slideText[1], 1); + id[0] = _gfx->createLabel(_menuFont, _location._slideText[0], 1); + id[1] = _gfx->createLabel(_menuFont, _location._slideText[1], 1); _gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 38); _gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 58); @@ -477,14 +478,7 @@ void Parallaction_ns::_c_endIntro(void *parm) { _gfx->updateScreen(); - for (uint16 v2 = 0; v2 < 100; v2++) { - _mouseButtons = kMouseNone; - readInput(); - if (_mouseButtons == kMouseLeftUp) - break; - - waitTime( 1 ); - } + _input->waitForButtonEvent(kMouseLeftUp, 5500); _gfx->freeLabels(); } @@ -497,7 +491,7 @@ void Parallaction_ns::_c_endIntro(void *parm) { id[0] = _gfx->createLabel(_menuFont, "CLICK MOUSE BUTTON TO START", 1); _gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 80); - waitUntilLeftClick(); + _input->waitUntilLeftClick(); _gfx->freeLabels(); @@ -507,7 +501,7 @@ void Parallaction_ns::_c_endIntro(void *parm) { cleanupGame(); } else { - waitUntilLeftClick(); + _input->waitUntilLeftClick(); } return; diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp index 4f281998e2..3c90a76f61 100644 --- a/engines/parallaction/debug.cpp +++ b/engines/parallaction/debug.cpp @@ -226,14 +226,14 @@ bool Debugger::Cmd_Programs(int argc, const char** argv) { int i = 1; - DebugPrintf("+---+--------------------+----------+\n" - "| # | bound animation | status |\n" - "+---+--------------------+----------+\n"); + DebugPrintf("+---+--------------------+--------+----------+\n" + "| # | bound animation | size | status |\n" + "+---+--------------------+--------+----------+\n"); for ( ; b != e; b++, i++) { ProgramPtr p = *b; - DebugPrintf("|%3i|%-20s|%-10s|\n", i, p->_anim->_name, status[p->_status] ); + DebugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] ); } - DebugPrintf("+---+--------------------+---------+\n"); + DebugPrintf("+---+--------------------+--------+----------+\n"); return true; } diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 2e3ecb590f..70db637699 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -24,6 +24,8 @@ */ #include "common/events.h" + +#include "parallaction/input.h" #include "parallaction/parallaction.h" @@ -195,7 +197,7 @@ void DialogueManager::displayQuestion() { _vm->_gfx->setItemFrame(id, _q->_mood & 0xF); _vm->_gfx->updateScreen(); - waitUntilLeftClick(); + _vm->_input->waitUntilLeftClick(); _vm->_gfx->hideDialogueStuff(); return; @@ -254,7 +256,7 @@ int16 DialogueManager::selectAnswer() { if (numAvailableAnswers == 1) { _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 0); - waitUntilLeftClick(); + _vm->_input->waitUntilLeftClick(); _vm->_gfx->hideDialogueStuff(); return 0; } @@ -262,10 +264,14 @@ int16 DialogueManager::selectAnswer() { int oldSelection = -1; int selection; + uint32 event; + Common::Point p; while (true) { - _vm->readInput(); - selection = _vm->_gfx->hitTestDialogueBalloon(_vm->_mousePos.x, _vm->_mousePos.y); + _vm->_input->readInput(); + _vm->_input->getCursorPos(p); + event = _vm->_input->getLastButtonEvent(); + selection = _vm->_gfx->hitTestDialogueBalloon(p.x, p.y); if (selection != oldSelection) { if (oldSelection != -1) { @@ -278,7 +284,7 @@ int16 DialogueManager::selectAnswer() { } } - if ((selection != -1) && (_mouseButtons == kMouseLeftUp)) { + if ((selection != -1) && (event == kMouseLeftUp)) { break; } diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index 21ff4aba76..b76c66aead 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -209,7 +209,7 @@ protected: protected: void errorFileNotFound(const char *s); Font *createFont(const char *name, Common::ReadStream &stream); - Sprites* createSprites(const char *name); + Sprites* createSprites(Common::ReadStream &stream); void loadBitmap(Common::SeekableReadStream &stream, Graphics::Surface &surf, byte *palette); public: diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index e4c4ce7492..5e88327879 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -139,12 +139,19 @@ DosDisk_br::~DosDisk_br() { } Frames* DosDisk_br::loadTalk(const char *name) { - debugC(5, kDebugDisk, "DosDisk_br::loadTalk"); + debugC(5, kDebugDisk, "DosDisk_br::loadTalk(%s)", name); + + Common::File stream; char path[PATH_LEN]; - sprintf(path, "%s/tal/%s.tal", _partPath, name); + sprintf(path, "%s/tal/%s", _partPath, name); + if (!stream.open(path)) { + sprintf(path, "%s/tal/%s.tal", _partPath, name); + if (!stream.open(path)) + errorFileNotFound(path); + } - return createSprites(path); + return createSprites(stream); } Script* DosDisk_br::loadLocation(const char *name) { @@ -252,12 +259,7 @@ Frames* DosDisk_br::loadStatic(const char* name) { return new SurfaceToFrames(surf); } -Sprites* DosDisk_br::createSprites(const char *path) { - - Common::File stream; - if (!stream.open(path)) { - errorFileNotFound(path); - } +Sprites* DosDisk_br::createSprites(Common::ReadStream &stream) { uint16 num = stream.readUint16LE(); @@ -284,7 +286,12 @@ Frames* DosDisk_br::loadFrames(const char* name) { char path[PATH_LEN]; sprintf(path, "%s/ani/%s", _partPath, name); - return createSprites(path); + Common::File stream; + if (!stream.open(path)) + errorFileNotFound(path); + + + return createSprites(stream); } // Slides in Nippon Safes are basically screen-sized pictures with valid diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index e4859a8851..3b67b4c370 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -23,7 +23,7 @@ * */ - +#include "parallaction/input.h" #include "parallaction/parallaction.h" namespace Parallaction { @@ -62,11 +62,13 @@ namespace Parallaction { -typedef OpcodeImpl<Parallaction_br> OpcodeV2; -#define COMMAND_OPCODE(op) OpcodeV2(this, &Parallaction_br::cmdOp_##op) +#define SetOpcodeTable(x) table = &x; + +typedef Common::Functor0Mem<void, Parallaction_br> OpcodeV2; +#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::cmdOp_##op)) #define DECLARE_COMMAND_OPCODE(op) void Parallaction_br::cmdOp_##op() -#define INSTRUCTION_OPCODE(op) OpcodeV2(this, &Parallaction_br::instOp_##op) +#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::instOp_##op)) #define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op() void Parallaction_br::setupSubtitles(char *s, char *s2, int y) { @@ -174,7 +176,8 @@ DECLARE_COMMAND_OPCODE(stop) { DECLARE_COMMAND_OPCODE(character) { - warning("Parallaction_br::cmdOp_character not yet implemented"); + debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _cmdRunCtxt.cmd->u._string); + changeCharacter(_cmdRunCtxt.cmd->u._string); } @@ -184,12 +187,12 @@ DECLARE_COMMAND_OPCODE(followme) { DECLARE_COMMAND_OPCODE(onmouse) { - showCursor(true); + _input->showCursor(true); } DECLARE_COMMAND_OPCODE(offmouse) { - showCursor(false); + _input->showCursor(false); } @@ -399,7 +402,7 @@ DECLARE_INSTRUCTION_OPCODE(inc) { } if (inst->_opA._flags & kParaLocal) { - wrapLocalVar(inst->_opA._local); + inst->_opA._local->wrap(); } } @@ -498,95 +501,85 @@ DECLARE_INSTRUCTION_OPCODE(endscript) { void Parallaction_br::initOpcodes() { - static const OpcodeV2 op1[] = { - COMMAND_OPCODE(invalid), - COMMAND_OPCODE(set), - COMMAND_OPCODE(clear), - COMMAND_OPCODE(start), - COMMAND_OPCODE(speak), - COMMAND_OPCODE(get), - COMMAND_OPCODE(location), - COMMAND_OPCODE(open), - COMMAND_OPCODE(close), - COMMAND_OPCODE(on), - COMMAND_OPCODE(off), - COMMAND_OPCODE(call), - COMMAND_OPCODE(toggle), - COMMAND_OPCODE(drop), - COMMAND_OPCODE(quit), - COMMAND_OPCODE(move), - COMMAND_OPCODE(stop), - COMMAND_OPCODE(character), - COMMAND_OPCODE(followme), - COMMAND_OPCODE(onmouse), - COMMAND_OPCODE(offmouse), - COMMAND_OPCODE(add), - COMMAND_OPCODE(leave), - COMMAND_OPCODE(inc), - COMMAND_OPCODE(dec), - COMMAND_OPCODE(ifeq), - COMMAND_OPCODE(iflt), - COMMAND_OPCODE(ifgt), - COMMAND_OPCODE(let), - COMMAND_OPCODE(music), - COMMAND_OPCODE(fix), - COMMAND_OPCODE(unfix), - COMMAND_OPCODE(zeta), - COMMAND_OPCODE(scroll), - COMMAND_OPCODE(swap), - COMMAND_OPCODE(give), - COMMAND_OPCODE(text), - COMMAND_OPCODE(part), - COMMAND_OPCODE(testsfx), - COMMAND_OPCODE(ret), - COMMAND_OPCODE(onsave), - COMMAND_OPCODE(offsave) - }; - - uint i; - for (i = 0; i < ARRAYSIZE(op1); i++) - _commandOpcodes.push_back(&op1[i]); - - - static const OpcodeV2 op2[] = { - INSTRUCTION_OPCODE(invalid), - INSTRUCTION_OPCODE(on), - INSTRUCTION_OPCODE(off), - INSTRUCTION_OPCODE(set), // x - INSTRUCTION_OPCODE(set), // y - INSTRUCTION_OPCODE(set), // z - INSTRUCTION_OPCODE(set), // f - INSTRUCTION_OPCODE(loop), - INSTRUCTION_OPCODE(endloop), - INSTRUCTION_OPCODE(null), // show - INSTRUCTION_OPCODE(inc), - INSTRUCTION_OPCODE(inc), // dec - INSTRUCTION_OPCODE(set), - INSTRUCTION_OPCODE(put), - INSTRUCTION_OPCODE(call), - INSTRUCTION_OPCODE(wait), - INSTRUCTION_OPCODE(start), - INSTRUCTION_OPCODE(process), - INSTRUCTION_OPCODE(move), - INSTRUCTION_OPCODE(color), - INSTRUCTION_OPCODE(process), // sound - INSTRUCTION_OPCODE(mask), - INSTRUCTION_OPCODE(print), - INSTRUCTION_OPCODE(text), - INSTRUCTION_OPCODE(inc), // mul - INSTRUCTION_OPCODE(inc), // div - INSTRUCTION_OPCODE(ifeq), - INSTRUCTION_OPCODE(iflt), - INSTRUCTION_OPCODE(ifgt), - INSTRUCTION_OPCODE(endif), - INSTRUCTION_OPCODE(stop), - INSTRUCTION_OPCODE(endscript) - }; - - for (i = 0; i < ARRAYSIZE(op2); i++) - _instructionOpcodes.push_back(&op2[i]); - - + Common::Array<const Opcode*> *table = 0; + + SetOpcodeTable(_commandOpcodes); + COMMAND_OPCODE(invalid); + COMMAND_OPCODE(set); + COMMAND_OPCODE(clear); + COMMAND_OPCODE(start); + COMMAND_OPCODE(speak); + COMMAND_OPCODE(get); + COMMAND_OPCODE(location); + COMMAND_OPCODE(open); + COMMAND_OPCODE(close); + COMMAND_OPCODE(on); + COMMAND_OPCODE(off); + COMMAND_OPCODE(call); + COMMAND_OPCODE(toggle); + COMMAND_OPCODE(drop); + COMMAND_OPCODE(quit); + COMMAND_OPCODE(move); + COMMAND_OPCODE(stop); + COMMAND_OPCODE(character); + COMMAND_OPCODE(followme); + COMMAND_OPCODE(onmouse); + COMMAND_OPCODE(offmouse); + COMMAND_OPCODE(add); + COMMAND_OPCODE(leave); + COMMAND_OPCODE(inc); + COMMAND_OPCODE(dec); + COMMAND_OPCODE(ifeq); + COMMAND_OPCODE(iflt); + COMMAND_OPCODE(ifgt); + COMMAND_OPCODE(let); + COMMAND_OPCODE(music); + COMMAND_OPCODE(fix); + COMMAND_OPCODE(unfix); + COMMAND_OPCODE(zeta); + COMMAND_OPCODE(scroll); + COMMAND_OPCODE(swap); + COMMAND_OPCODE(give); + COMMAND_OPCODE(text); + COMMAND_OPCODE(part); + COMMAND_OPCODE(testsfx); + COMMAND_OPCODE(ret); + COMMAND_OPCODE(onsave); + COMMAND_OPCODE(offsave); + + SetOpcodeTable(_instructionOpcodes); + INSTRUCTION_OPCODE(invalid); + INSTRUCTION_OPCODE(on); + INSTRUCTION_OPCODE(off); + INSTRUCTION_OPCODE(set); // x + INSTRUCTION_OPCODE(set); // y + INSTRUCTION_OPCODE(set); // z + INSTRUCTION_OPCODE(set); // f + INSTRUCTION_OPCODE(loop); + INSTRUCTION_OPCODE(endloop); + INSTRUCTION_OPCODE(null); // show + INSTRUCTION_OPCODE(inc); + INSTRUCTION_OPCODE(inc); // dec + INSTRUCTION_OPCODE(set); + INSTRUCTION_OPCODE(put); + INSTRUCTION_OPCODE(call); + INSTRUCTION_OPCODE(wait); + INSTRUCTION_OPCODE(start); + INSTRUCTION_OPCODE(process); + INSTRUCTION_OPCODE(move); + INSTRUCTION_OPCODE(color); + INSTRUCTION_OPCODE(process); // sound + INSTRUCTION_OPCODE(mask); + INSTRUCTION_OPCODE(print); + INSTRUCTION_OPCODE(text); + INSTRUCTION_OPCODE(inc); // mul + INSTRUCTION_OPCODE(inc); // div + INSTRUCTION_OPCODE(ifeq); + INSTRUCTION_OPCODE(iflt); + INSTRUCTION_OPCODE(ifgt); + INSTRUCTION_OPCODE(endif); + INSTRUCTION_OPCODE(stop); + INSTRUCTION_OPCODE(endscript); } #if 0 diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index 385e49b78d..a4b372f42a 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -23,6 +23,7 @@ * */ +#include "parallaction/input.h" #include "parallaction/parallaction.h" #include "parallaction/sound.h" @@ -49,12 +50,13 @@ namespace Parallaction { #define INST_MOVE 18 #define INST_ENDSCRIPT 19 +#define SetOpcodeTable(x) table = &x; -typedef OpcodeImpl<Parallaction_ns> OpcodeV1; -#define COMMAND_OPCODE(op) OpcodeV1(this, &Parallaction_ns::cmdOp_##op) +typedef Common::Functor0Mem<void, Parallaction_ns> OpcodeV2; +#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::cmdOp_##op)) #define DECLARE_COMMAND_OPCODE(op) void Parallaction_ns::cmdOp_##op() -#define INSTRUCTION_OPCODE(op) OpcodeV1(this, &Parallaction_ns::instOp_##op) +#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::instOp_##op)) #define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_ns::instOp_##op() @@ -107,7 +109,7 @@ DECLARE_INSTRUCTION_OPCODE(inc) { } if (inst->_opA._flags & kParaLocal) { - wrapLocalVar(inst->_opA._local); + inst->_opA._local->wrap(); } } @@ -189,16 +191,6 @@ DECLARE_INSTRUCTION_OPCODE(endscript) { -void Parallaction_ns::wrapLocalVar(LocalVariable *local) { - - if (local->_value >= local->_max) - local->_value = local->_min; - if (local->_value < local->_min) - local->_value = local->_max - 1; - - return; -} - DECLARE_COMMAND_OPCODE(invalid) { error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id); @@ -371,7 +363,6 @@ void Parallaction_ns::runScripts() { debugC(9, kDebugExec, "runScripts"); - static uint16 modCounter = 0; for (ProgramList::iterator it = _location._programs.begin(); it != _location._programs.end(); it++) { @@ -389,7 +380,7 @@ void Parallaction_ns::runScripts() { (*it)->_status = kProgramRunning; - debugC(9, kDebugExec, "Animation: %s, instruction: %s", a->_name, _instructionNamesRes[(*inst)->_index - 1]); + debugC(9, kDebugExec, "Animation: %s, instruction: %i", a->_name, (*inst)->_index); //_instructionNamesRes[(*inst)->_index - 1]); _instRunCtxt.inst = inst; _instRunCtxt.anim = AnimationPtr(a); @@ -446,7 +437,7 @@ void Parallaction::runCommands(CommandList& list, ZonePtr z) { if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue; if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue; - debugC(3, kDebugExec, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff); +// debugC(3, kDebugExec, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff); _cmdRunCtxt.z = z; _cmdRunCtxt.cmd = cmd; @@ -491,7 +482,7 @@ void Parallaction::displayComment(ExamineData *data) { _gfx->setItemFrame(id, 0); } - _inputMode = kInputModeComment; + _input->_inputMode = Input::kInputModeComment; } @@ -663,56 +654,48 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) { void Parallaction_ns::initOpcodes() { - static const OpcodeV1 op1[] = { - INSTRUCTION_OPCODE(invalid), - INSTRUCTION_OPCODE(on), - INSTRUCTION_OPCODE(off), - INSTRUCTION_OPCODE(set), // x - INSTRUCTION_OPCODE(set), // y - INSTRUCTION_OPCODE(set), // z - INSTRUCTION_OPCODE(set), // f - INSTRUCTION_OPCODE(loop), - INSTRUCTION_OPCODE(endloop), - INSTRUCTION_OPCODE(null), - INSTRUCTION_OPCODE(inc), - INSTRUCTION_OPCODE(inc), // dec - INSTRUCTION_OPCODE(set), - INSTRUCTION_OPCODE(put), - INSTRUCTION_OPCODE(call), - INSTRUCTION_OPCODE(wait), - INSTRUCTION_OPCODE(start), - INSTRUCTION_OPCODE(sound), - INSTRUCTION_OPCODE(move), - INSTRUCTION_OPCODE(endscript) - }; - - uint i; - for (i = 0; i < ARRAYSIZE(op1); i++) - _instructionOpcodes.push_back(&op1[i]); - - static const OpcodeV1 op3[] = { - COMMAND_OPCODE(invalid), - COMMAND_OPCODE(set), - COMMAND_OPCODE(clear), - COMMAND_OPCODE(start), - COMMAND_OPCODE(speak), - COMMAND_OPCODE(get), - COMMAND_OPCODE(location), - COMMAND_OPCODE(open), - COMMAND_OPCODE(close), - COMMAND_OPCODE(on), - COMMAND_OPCODE(off), - COMMAND_OPCODE(call), - COMMAND_OPCODE(toggle), - COMMAND_OPCODE(drop), - COMMAND_OPCODE(quit), - COMMAND_OPCODE(move), - COMMAND_OPCODE(stop) - }; - - for (i = 0; i < ARRAYSIZE(op3); i++) - _commandOpcodes.push_back(&op3[i]); - + Common::Array<const Opcode*> *table = 0; + + SetOpcodeTable(_instructionOpcodes); + INSTRUCTION_OPCODE(invalid); + INSTRUCTION_OPCODE(on); + INSTRUCTION_OPCODE(off); + INSTRUCTION_OPCODE(set); // x + INSTRUCTION_OPCODE(set); // y + INSTRUCTION_OPCODE(set); // z + INSTRUCTION_OPCODE(set); // f + INSTRUCTION_OPCODE(loop); + INSTRUCTION_OPCODE(endloop); + INSTRUCTION_OPCODE(null); + INSTRUCTION_OPCODE(inc); + INSTRUCTION_OPCODE(inc); // dec + INSTRUCTION_OPCODE(set); + INSTRUCTION_OPCODE(put); + INSTRUCTION_OPCODE(call); + INSTRUCTION_OPCODE(wait); + INSTRUCTION_OPCODE(start); + INSTRUCTION_OPCODE(sound); + INSTRUCTION_OPCODE(move); + INSTRUCTION_OPCODE(endscript); + + SetOpcodeTable(_commandOpcodes); + COMMAND_OPCODE(invalid); + COMMAND_OPCODE(set); + COMMAND_OPCODE(clear); + COMMAND_OPCODE(start); + COMMAND_OPCODE(speak); + COMMAND_OPCODE(get); + COMMAND_OPCODE(location); + COMMAND_OPCODE(open); + COMMAND_OPCODE(close); + COMMAND_OPCODE(on); + COMMAND_OPCODE(off); + COMMAND_OPCODE(call); + COMMAND_OPCODE(toggle); + COMMAND_OPCODE(drop); + COMMAND_OPCODE(quit); + COMMAND_OPCODE(move); + COMMAND_OPCODE(stop); } diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp index bc67acf644..91848b30a4 100644 --- a/engines/parallaction/font.cpp +++ b/engines/parallaction/font.cpp @@ -96,7 +96,7 @@ public: return (uint16)_height; } - uint16 drawChar(char c) { + uint16 drawChar(unsigned char c) { assert(c < _numGlyphs); byte *src = _data + _offsets[c]; diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index f92a58cdb0..58fb02a750 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -27,15 +27,12 @@ #include "common/file.h" #include "graphics/primitives.h" +#include "parallaction/input.h" #include "parallaction/parallaction.h" namespace Parallaction { - -typedef Common::HashMap<Common::String, int32, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VarMap; -VarMap _vars; - void Gfx::registerVar(const Common::String &name, int32 initialValue) { if (_vars.contains(name)) { warning("Variable '%s' already registered, ignoring initial value.\n", name.c_str()); @@ -781,9 +778,9 @@ void Gfx::updateFloatingLabel() { int16 _si, _di; Common::Point cursor; - _vm->getCursorPos(cursor); + _vm->_input->getCursorPos(cursor); - if (_vm->_activeItem._id != 0) { + if (_vm->_input->_activeItem._id != 0) { _si = cursor.x + 16 - _floatingLabel->_cnv.w/2; _di = cursor.y + 34; } else { diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 8f1c14aef0..894e0fd678 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -452,10 +452,13 @@ enum { kBackgroundSlide = 2 }; +typedef Common::HashMap<Common::String, int32, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VarMap; + class Gfx { public: Disk *_disk; + VarMap _vars; GfxObjList _gfxobjList[3]; GfxObj* loadAnim(const char *name); diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp index 8ce559e644..c515299a34 100644 --- a/engines/parallaction/gui_br.cpp +++ b/engines/parallaction/gui_br.cpp @@ -25,6 +25,8 @@ #include "common/system.h" + +#include "parallaction/input.h" #include "parallaction/parallaction.h" namespace Parallaction { @@ -164,15 +166,20 @@ int Parallaction_br::guiShowMenu() { setMousePointer(0); + uint32 event; + Common::Point p; while (true) { - if ((_mouseButtons == kMouseLeftUp) && selectedItem >= 0) + _input->readInput(); + + event = _input->getLastButtonEvent(); + if ((event == kMouseLeftUp) && selectedItem >= 0) break; - readInput(); + _input->getCursorPos(p); - if ((_mousePos.x > MENUITEMS_X) && (_mousePos.x < (MENUITEMS_X+MENUITEM_WIDTH)) && (_mousePos.y > MENUITEMS_Y)) { - selectedItem = (_mousePos.y - MENUITEMS_Y) / MENUITEM_HEIGHT; + if ((p.x > MENUITEMS_X) && (p.x < (MENUITEMS_X+MENUITEM_WIDTH)) && (p.y > MENUITEMS_Y)) { + selectedItem = (p.y - MENUITEMS_Y) / MENUITEM_HEIGHT; if (!(selectedItem < availItems)) selectedItem = -1; diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp index fec5695413..1d4d44fa46 100644 --- a/engines/parallaction/gui_ns.cpp +++ b/engines/parallaction/gui_ns.cpp @@ -25,6 +25,7 @@ #include "common/system.h" +#include "parallaction/input.h" #include "parallaction/parallaction.h" #include "parallaction/sound.h" @@ -206,20 +207,18 @@ int Parallaction_ns::guiNewGame() { _gfx->showLabel(id[2], CENTER_LABEL_HORIZONTAL, 100); _gfx->showLabel(id[3], CENTER_LABEL_HORIZONTAL, 120); - showCursor(false); + _input->showCursor(false); _gfx->updateScreen(); - _mouseButtons = kMouseNone; - do { - readInput(); - } while (_mouseButtons != kMouseLeftUp && _mouseButtons != kMouseRightUp); + _input->waitForButtonEvent(kMouseLeftUp | kMouseRightUp); + uint32 event = _input->getLastButtonEvent(); - showCursor(true); + _input->showCursor(true); _gfx->freeLabels(); - if (_mouseButtons != kMouseRightUp) { + if (event != kMouseRightUp) { return START_INTRO; } @@ -267,11 +266,14 @@ uint16 Parallaction_ns::guiChooseLanguage() { setArrowCursor(); + Common::Point p; + int selection = -1; while (selection == -1) { - waitUntilLeftClick(); + _input->waitUntilLeftClick(); + _input->getCursorPos(p); for (uint16 i = 0; i < 4; i++) { - if (blocks[i].contains(_mousePos)) { + if (blocks[i].contains(p)) { selection = i; break; } @@ -299,12 +301,18 @@ uint16 Parallaction_ns::guiSelectGame() { id0 = _gfx->createLabel(_introFont, loadGameMsg[_language], 1); id1 = _gfx->createLabel(_introFont, newGameMsg[_language], 1); - _mouseButtons = kMouseNone; - while (_mouseButtons != kMouseLeftUp) { + Common::Point p; + + _input->readInput(); + uint32 event = _input->getLastButtonEvent(); + + while (event != kMouseLeftUp) { - readInput(); + _input->readInput(); + _input->getCursorPos(p); + event = _input->getLastButtonEvent(); - _si = (_mousePos.x > 160) ? 1 : 0; + _si = (p.x > 160) ? 1 : 0; if (_si != _di) { if (_si != 0) { @@ -409,6 +417,8 @@ int Parallaction_ns::guiSelectCharacter() { Graphics::Surface block; block.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1); + Common::Point p; + while (true) { points[0] = 0; @@ -422,8 +432,10 @@ int Parallaction_ns::guiSelectCharacter() { _di = 0; while (_di < PASSWORD_LEN) { - waitUntilLeftClick(); - int _si = guiGetSelectedBlock(_mousePos); + _input->waitUntilLeftClick(); + _input->getCursorPos(p); + + int _si = guiGetSelectedBlock(p); if (_si != -1) { _gfx->grabBackground(codeTrueBlocks[_si], block); diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp new file mode 100644 index 0000000000..28d0ad888d --- /dev/null +++ b/engines/parallaction/input.cpp @@ -0,0 +1,332 @@ +/* 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 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/events.h" + +#include "parallaction/input.h" +#include "parallaction/parallaction.h" +#include "parallaction/debug.h" + +namespace Parallaction { + +// FIXME: the engine has 3 event loops. The following routine hosts the main one, +// and it's called from 8 different places in the code. There exist 2 more specialised +// loops which could possibly be merged into this one with some effort in changing +// caller code, i.e. adding condition checks. +// +uint16 Input::readInput() { + + Common::Event e; + uint16 KeyDown = 0; + + _mouseButtons = kMouseNone; + + Common::EventManager *eventMan = _vm->_system->getEventManager(); + while (eventMan->pollEvent(e)) { + + switch (e.type) { + case Common::EVENT_KEYDOWN: + if (e.kbd.flags == Common::KBD_CTRL && e.kbd.keycode == 'd') + _vm->_debugger->attach(); + if (_vm->getFeatures() & GF_DEMO) break; + if (e.kbd.keycode == Common::KEYCODE_l) KeyDown = kEvLoadGame; + if (e.kbd.keycode == Common::KEYCODE_s) KeyDown = kEvSaveGame; + break; + + case Common::EVENT_LBUTTONDOWN: + _mouseButtons = kMouseLeftDown; + _mousePos = e.mouse; + break; + + case Common::EVENT_LBUTTONUP: + _mouseButtons = kMouseLeftUp; + _mousePos = e.mouse; + break; + + case Common::EVENT_RBUTTONDOWN: + _mouseButtons = kMouseRightDown; + _mousePos = e.mouse; + break; + + case Common::EVENT_RBUTTONUP: + _mouseButtons = kMouseRightUp; + _mousePos = e.mouse; + break; + + case Common::EVENT_MOUSEMOVE: + _mousePos = e.mouse; + break; + + case Common::EVENT_QUIT: + // TODO: don't quit() here, just have caller routines to check + // on kEngineQuit and exit gracefully to allow the engine to shut down + _engineFlags |= kEngineQuit; + _vm->_system->quit(); + break; + + default: + break; + + } + + } + + if (_vm->_debugger->isAttached()) + _vm->_debugger->onFrame(); + + return KeyDown; + +} + +// FIXME: see comment for readInput() +void Input::waitForButtonEvent(uint32 buttonEventMask, int32 timeout) { + + if (buttonEventMask == kMouseNone) { + _mouseButtons = kMouseNone; // don't wait on nothing + return; + } + + const int32 LOOP_RESOLUTION = 30; + if (timeout <= 0) { + do { + readInput(); + _vm->_system->delayMillis(LOOP_RESOLUTION); + } while ((_mouseButtons & buttonEventMask) == 0); + } else { + do { + readInput(); + _vm->_system->delayMillis(LOOP_RESOLUTION); + timeout -= LOOP_RESOLUTION; + } while ((timeout > 0) && (_mouseButtons & buttonEventMask) == 0); + } + +} + +// FIXME: see comment for readInput() +void Input::waitUntilLeftClick() { + + do { + readInput(); + _vm->_gfx->updateScreen(); + _vm->_system->delayMillis(30); + } while (_mouseButtons != kMouseLeftUp); + + return; +} + + +void Input::updateGameInput() { + + int16 keyDown = readInput(); + + debugC(3, kDebugInput, "translateInput: input flags (%i, %i, %i, %i)", + !_mouseHidden, + (_engineFlags & kEngineBlockInput) == 0, + (_engineFlags & kEngineWalking) == 0, + (_engineFlags & kEngineChangeLocation) == 0 + ); + + if ((_mouseHidden) || + (_engineFlags & kEngineBlockInput) || + (_engineFlags & kEngineWalking) || + (_engineFlags & kEngineChangeLocation)) { + + return; + } + + if (keyDown == kEvQuitGame) { + _inputData._event = kEvQuitGame; + } else + if (keyDown == kEvSaveGame) { + _inputData._event = kEvSaveGame; + } else + if (keyDown == kEvLoadGame) { + _inputData._event = kEvLoadGame; + } else { + _inputData._mousePos = _mousePos; + _inputData._event = kEvNone; + if (!translateGameInput()) { + translateInventoryInput(); + } + } + +} + +void Input::updateCommentInput() { + waitUntilLeftClick(); + + _vm->_gfx->hideDialogueStuff(); + _vm->_gfx->setHalfbriteMode(false); + + _inputMode = kInputModeGame; +} + +InputData* Input::updateInput() { + + _inputData._event = kEvNone; + + switch (_inputMode) { + case kInputModeComment: + updateCommentInput(); + break; + + case kInputModeGame: + updateGameInput(); + break; + } + + return &_inputData; +} + +bool Input::translateGameInput() { + + if ((_engineFlags & kEnginePauseJobs) || (_engineFlags & kEngineInventory)) { + return false; + } + + if (_actionAfterWalk) { + // if walking is over, then take programmed action + _inputData._event = kEvAction; + _actionAfterWalk = false; + return true; + } + + if (_mouseButtons == kMouseRightDown) { + // right button down shows inventory + + if (_vm->hitZone(kZoneYou, _mousePos.x, _mousePos.y) && (_activeItem._id != 0)) { + _activeItem._index = (_activeItem._id >> 16) & 0xFFFF; + _engineFlags |= kEngineDragging; + } + + _inputData._event = kEvOpenInventory; + _transCurrentHoverItem = -1; + return true; + } + + // test if mouse is hovering on an interactive zone for the currently selected inventory item + ZonePtr z = _vm->hitZone(_activeItem._id, _mousePos.x, _mousePos.y); + + if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((_engineFlags & kEngineWalking) == 0)) && ((!z) || ((z->_type & 0xFFFF) != kZoneCommand))) { + _inputData._event = kEvWalk; + return true; + } + + if ((z != _hoverZone) && (_hoverZone)) { + _hoverZone = nullZonePtr; + _inputData._event = kEvExitZone; + return true; + } + + if (!z) { + _inputData._event = kEvNone; + return true; + } + + if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) { + _hoverZone = z; + _inputData._event = kEvEnterZone; + _inputData._label = z->_label; + return true; + } + + if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) { + + _inputData._zone = z; + if (z->_flags & kFlagsNoWalk) { + // character doesn't need to walk to take specified action + _inputData._event = kEvAction; + + } else { + // action delayed: if Zone defined a moveto position the character is programmed to move there, + // else it will move to the mouse position + _inputData._event = kEvWalk; + _actionAfterWalk = true; + if (z->_moveTo.y != 0) { + _inputData._mousePos = z->_moveTo; + } + } + + _vm->beep(); + _vm->setArrowCursor(); + return true; + } + + return true; + +} + +bool Input::translateInventoryInput() { + + if ((_engineFlags & kEngineInventory) == 0) { + return false; + } + + // in inventory + int16 _si = _vm->getHoverInventoryItem(_mousePos.x, _mousePos.y); + + if (_mouseButtons == kMouseRightUp) { + // right up hides inventory + + _inputData._event = kEvCloseInventory; + _inputData._inventoryIndex = _vm->getHoverInventoryItem(_mousePos.x, _mousePos.y); + _vm->highlightInventoryItem(-1); // disable + + if ((_engineFlags & kEngineDragging) == 0) { + return true; + } + + _engineFlags &= ~kEngineDragging; + ZonePtr z = _vm->hitZone(kZoneMerge, _activeItem._index, _vm->getInventoryItemIndex(_inputData._inventoryIndex)); + + if (z) { + _vm->dropItem(z->u.merge->_obj1); + _vm->dropItem(z->u.merge->_obj2); + _vm->addInventoryItem(z->u.merge->_obj3); + _vm->runCommands(z->_commands); + } + + return true; + } + + if (_si == _transCurrentHoverItem) { + _inputData._event = kEvNone; + return true; + } + + _transCurrentHoverItem = _si; + _inputData._event = kEvHoverInventory; + _inputData._inventoryIndex = _si; + return true; + +} + +void Input::showCursor(bool visible) { + _mouseHidden = !visible; + _vm->_system->showMouse(visible); +} + + +} // namespace Parallaction diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h new file mode 100644 index 0000000000..46dbb08c4e --- /dev/null +++ b/engines/parallaction/input.h @@ -0,0 +1,114 @@ +/* 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 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$ + * + */ + +#ifndef PARALLACTION_INPUT_H +#define PARALLACTION_INPUT_H + +#include "parallaction/objects.h" +#include "parallaction/inventory.h" + +namespace Parallaction { + +enum { + kMouseNone = 0, + kMouseLeftUp = 1, + kMouseLeftDown = 2, + kMouseRightUp = 4, + kMouseRightDown = 8 +}; + +struct InputData { + uint16 _event; + Common::Point _mousePos; + int16 _inventoryIndex; + ZonePtr _zone; + Label* _label; +}; + +class Input { + void updateGameInput(); + void updateCommentInput(); + + // input-only + InputData _inputData; + bool _actionAfterWalk; // actived when the character needs to move before taking an action + // these two could/should be merged as they carry on the same duty in two member functions, + // respectively processInput and translateInput + int16 _transCurrentHoverItem; + + InputData *translateInput(); + bool translateGameInput(); + bool translateInventoryInput(); + + Parallaction *_vm; + + Common::Point _mousePos; + uint16 _mouseButtons; + + bool _mouseHidden; + ZonePtr _hoverZone; + +public: + enum { + kInputModeGame = 0, + kInputModeComment = 1 + }; + + + Input(Parallaction *vm) : _vm(vm) { + _transCurrentHoverItem = 0; + _actionAfterWalk = false; // actived when the character needs to move before taking an action + _mouseHidden = false; + _activeItem._index = 0; + _activeItem._id = 0; + _mouseButtons = 0; + } + + virtual ~Input() { } + + + void showCursor(bool visible); + void getCursorPos(Common::Point& p) { + p = _mousePos; + } + + int _inputMode; + InventoryItem _activeItem; + + uint16 readInput(); + InputData* updateInput(); + void waitUntilLeftClick(); + void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1); + uint32 getLastButtonEvent() { return _mouseButtons; } + + void stopHovering() { + _hoverZone = nullZonePtr; + } + +}; + +} // namespace Parallaction + +#endif diff --git a/engines/parallaction/inventory.cpp b/engines/parallaction/inventory.cpp index 05202809a9..58848196d7 100644 --- a/engines/parallaction/inventory.cpp +++ b/engines/parallaction/inventory.cpp @@ -23,7 +23,7 @@ * */ - +#include "parallaction/input.h" #include "parallaction/parallaction.h" @@ -52,8 +52,18 @@ int16 Parallaction::getHoverInventoryItem(int16 x, int16 y) { return _inventoryRenderer->hitTest(Common::Point(x,y)); } -void Parallaction::highlightInventoryItem(ItemPosition pos, byte color) { - _inventoryRenderer->highlightItem(pos, color); +void Parallaction::highlightInventoryItem(ItemPosition pos) { + static ItemPosition lastHighlightedPos = -1; + + if (lastHighlightedPos != -1) { + _inventoryRenderer->highlightItem(lastHighlightedPos, 12); + } + + if (pos != -1) { + _inventoryRenderer->highlightItem(pos, 19); + } + + lastHighlightedPos = pos; } int Parallaction::addInventoryItem(ItemName item) { @@ -125,8 +135,11 @@ void InventoryRenderer::showInventory() { uint16 lines = getNumLines(); - _pos.x = CLIP(_vm->_mousePos.x - (INVENTORY_WIDTH / 2), 0, (int)(_vm->_screenWidth - INVENTORY_WIDTH)); - _pos.y = CLIP(_vm->_mousePos.y - 2 - (lines * INVENTORYITEM_HEIGHT), 0, (int)(_vm->_screenHeight - lines * INVENTORYITEM_HEIGHT)); + Common::Point p; + _vm->_input->getCursorPos(p); + + _pos.x = CLIP(p.x - (INVENTORY_WIDTH / 2), 0, (int)(_vm->_screenWidth - INVENTORY_WIDTH)); + _pos.y = CLIP(p.y - 2 - (lines * INVENTORYITEM_HEIGHT), 0, (int)(_vm->_screenHeight - lines * INVENTORYITEM_HEIGHT)); refresh(); } diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index c7e7af14bf..2478b4b2e1 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -15,6 +15,7 @@ MODULE_OBJS := \ graphics.o \ gui_br.o \ gui_ns.o \ + input.o \ inventory.o \ objects.o \ parallaction.o \ diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 0491c5c3c7..cac31911f4 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -116,6 +116,16 @@ int16 Program::addLocal(const char *name, int16 value, int16 min, int16 max) { return _numLocals++; } +void LocalVariable::wrap() { + + if (_value >= _max) + _value = _min; + if (_value < _min) + _value = _max - 1; + + return; +} + Zone::Zone() { diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index cfb78f941b..afa6cc5ed5 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -94,7 +94,7 @@ enum ZoneFlags { enum CommandFlags { - kFlagsAll = 0xFFFFFFFF, + kFlagsAll = 0xFFFFFFFFU, kFlagsVisited = 1, kFlagsExit = 0x10000000, @@ -106,7 +106,6 @@ enum CommandFlags { }; - struct CommandData { uint32 _flags; ZonePtr _zone; @@ -317,6 +316,8 @@ struct LocalVariable { _min = -10000; _max = 10000; } + + void wrap(); }; enum ParaFlags { diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 649f21ae96..d66b1af1f1 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -31,6 +31,8 @@ #include "sound/mididrv.h" #include "sound/mixer.h" + +#include "parallaction/input.h" #include "parallaction/parallaction.h" #include "parallaction/debug.h" #include "parallaction/sound.h" @@ -44,9 +46,6 @@ Parallaction *_vm = NULL; // public stuff -uint16 _mouseButtons = 0; - - char _saveData1[30] = { '\0' }; uint16 _language = 0; uint32 _engineFlags = 0; @@ -67,8 +66,6 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam // FIXME _vm = this; - _mouseHidden = false; - Common::File::addDefaultDirectory( _gameDataPath ); Common::addSpecialDebugLevel(kDebugDialogue, "dialogue", "Dialogues debug level"); @@ -89,13 +86,10 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam Parallaction::~Parallaction() { delete _debugger; - delete _locationParser; delete _globalTable; delete _callableNames; delete _localFlagNames; - delete _zoneTypeNames; - delete _zoneFlagNames; freeLocation(); @@ -114,11 +108,6 @@ int Parallaction::init() { _objectsNames = NULL; _globalTable = NULL; _location._hasSound = false; - _transCurrentHoverItem = 0; - _actionAfterWalk = false; // actived when the character needs to move before taking an action - _activeItem._index = 0; - _activeItem._id = 0; - _procCurrentHoverItem = -1; _baseTime = 0; _numLocations = 0; _location._startPosition.x = -1000; @@ -137,6 +126,8 @@ int Parallaction::init() { initInventory(); // needs to be pushed into subclass + _input = new Input(this); + _gfx = new Gfx(this); _debugger = new Debugger(this); @@ -150,111 +141,6 @@ int Parallaction::init() { -// FIXME: the engine has 3 event loops. The following routine hosts the main one, -// and it's called from 8 different places in the code. There exist 2 more specialised -// loops which could possibly be merged into this one with some effort in changing -// caller code, i.e. adding condition checks. -// -uint16 Parallaction::readInput() { - - Common::Event e; - uint16 KeyDown = 0; - - _mouseButtons = kMouseNone; - - Common::EventManager *eventMan = _system->getEventManager(); - while (eventMan->pollEvent(e)) { - - switch (e.type) { - case Common::EVENT_KEYDOWN: - if (e.kbd.flags == Common::KBD_CTRL && e.kbd.keycode == 'd') - _debugger->attach(); - if (getFeatures() & GF_DEMO) break; - if (e.kbd.keycode == Common::KEYCODE_l) KeyDown = kEvLoadGame; - if (e.kbd.keycode == Common::KEYCODE_s) KeyDown = kEvSaveGame; - break; - - case Common::EVENT_LBUTTONDOWN: - _mouseButtons = kMouseLeftDown; - _mousePos = e.mouse; - break; - - case Common::EVENT_LBUTTONUP: - _mouseButtons = kMouseLeftUp; - _mousePos = e.mouse; - break; - - case Common::EVENT_RBUTTONDOWN: - _mouseButtons = kMouseRightDown; - _mousePos = e.mouse; - break; - - case Common::EVENT_RBUTTONUP: - _mouseButtons = kMouseRightUp; - _mousePos = e.mouse; - break; - - case Common::EVENT_MOUSEMOVE: - _mousePos = e.mouse; - break; - - case Common::EVENT_QUIT: - // TODO: don't quit() here, just have caller routines to check - // on kEngineQuit and exit gracefully to allow the engine to shut down - _engineFlags |= kEngineQuit; - g_system->quit(); - break; - - default: - break; - - } - - } - - if (_debugger->isAttached()) - _debugger->onFrame(); - - return KeyDown; - -} - -// FIXME: see comment for readInput() -void waitUntilLeftClick() { - - do { - _vm->readInput(); - _vm->_gfx->updateScreen(); - g_system->delayMillis(30); - } while (_mouseButtons != kMouseLeftUp); - - return; -} - -void Parallaction::runGame() { - - updateInput(); - - runPendingZones(); - - if (_engineFlags & kEngineChangeLocation) { - changeLocation(_location._name); - } - - - _gfx->beginFrame(); - - if (_inputMode == kInputModeGame) { - runScripts(); - walk(); - drawAnimations(); - } - - // change this to endFrame? - updateView(); - -} - void Parallaction::updateView() { if ((_engineFlags & kEnginePauseJobs) && (_engineFlags & kEngineInventory) == 0) { @@ -267,301 +153,6 @@ void Parallaction::updateView() { } -void Parallaction::processInput(InputData *data) { - - switch (data->_event) { - case kEvEnterZone: - debugC(2, kDebugInput, "processInput: kEvEnterZone"); - _gfx->setFloatingLabel(data->_label); - break; - - case kEvExitZone: - debugC(2, kDebugInput, "processInput: kEvExitZone"); - _gfx->setFloatingLabel(0); - break; - - case kEvAction: - debugC(2, kDebugInput, "processInput: kEvAction"); - _procCurrentHoverItem = -1; - _hoverZone = nullZonePtr; - pauseJobs(); - runZone(data->_zone); - resumeJobs(); - break; - - case kEvOpenInventory: - _procCurrentHoverItem = -1; - _hoverZone = nullZonePtr; - _gfx->setFloatingLabel(0); - if (hitZone(kZoneYou, _mousePos.x, _mousePos.y) == 0) { - setArrowCursor(); - } - pauseJobs(); - openInventory(); - break; - - case kEvCloseInventory: // closes inventory and possibly select item - closeInventory(); - setInventoryCursor(data->_inventoryIndex); - resumeJobs(); - break; - - case kEvHoverInventory: - highlightInventoryItem(_procCurrentHoverItem, 12); // disable - highlightInventoryItem(data->_inventoryIndex, 19); // enable - _procCurrentHoverItem = data->_inventoryIndex; - break; - - case kEvWalk: - debugC(2, kDebugInput, "processInput: kEvWalk"); - _hoverZone = nullZonePtr; - setArrowCursor(); - _char.scheduleWalk(data->_mousePos.x, data->_mousePos.y); - break; - - case kEvQuitGame: - _engineFlags |= kEngineQuit; - break; - - case kEvSaveGame: - _hoverZone = nullZonePtr; - saveGame(); - setArrowCursor(); - break; - - case kEvLoadGame: - _hoverZone = nullZonePtr; - loadGame(); - setArrowCursor(); - break; - - } - - return; -} - - - - - -void Parallaction::updateGameInput() { - - int16 keyDown = readInput(); - - debugC(3, kDebugInput, "translateInput: input flags (%i, %i, %i, %i)", - !_mouseHidden, - (_engineFlags & kEngineBlockInput) == 0, - (_engineFlags & kEngineWalking) == 0, - (_engineFlags & kEngineChangeLocation) == 0 - ); - - if ((_mouseHidden) || - (_engineFlags & kEngineBlockInput) || - (_engineFlags & kEngineWalking) || - (_engineFlags & kEngineChangeLocation)) { - - return; - } - - if (keyDown == kEvQuitGame) { - _input._event = kEvQuitGame; - } else - if (keyDown == kEvSaveGame) { - _input._event = kEvSaveGame; - } else - if (keyDown == kEvLoadGame) { - _input._event = kEvLoadGame; - } else { - _input._mousePos = _mousePos; - _input._event = kEvNone; - if (!translateGameInput()) { - translateInventoryInput(); - } - } - - if (_input._event != kEvNone) - processInput(&_input); - -} - -void Parallaction::updateCommentInput() { - waitUntilLeftClick(); - - _gfx->hideDialogueStuff(); - _gfx->setHalfbriteMode(false); - - _inputMode = kInputModeGame; -} - -void Parallaction::updateInput() { - - switch (_inputMode) { - case kInputModeComment: - updateCommentInput(); - break; - - case kInputModeGame: - updateGameInput(); - break; - } - - return; -} - -bool Parallaction::translateGameInput() { - - if ((_engineFlags & kEnginePauseJobs) || (_engineFlags & kEngineInventory)) { - return false; - } - - if (_actionAfterWalk) { - // if walking is over, then take programmed action - _input._event = kEvAction; - _actionAfterWalk = false; - return true; - } - - if (_mouseButtons == kMouseRightDown) { - // right button down shows inventory - - if (hitZone(kZoneYou, _mousePos.x, _mousePos.y) && (_activeItem._id != 0)) { - _activeItem._index = (_activeItem._id >> 16) & 0xFFFF; - _engineFlags |= kEngineDragging; - } - - _input._event = kEvOpenInventory; - _transCurrentHoverItem = -1; - return true; - } - - // test if mouse is hovering on an interactive zone for the currently selected inventory item - ZonePtr z = hitZone(_activeItem._id, _mousePos.x, _mousePos.y); - - if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((_engineFlags & kEngineWalking) == 0)) && ((!z) || ((z->_type & 0xFFFF) != kZoneCommand))) { - _input._event = kEvWalk; - return true; - } - - if ((z != _hoverZone) && (_hoverZone)) { - _hoverZone = nullZonePtr; - _input._event = kEvExitZone; - return true; - } - - if (!z) { - _input._event = kEvNone; - return true; - } - - if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) { - _hoverZone = z; - _input._event = kEvEnterZone; - _input._label = z->_label; - return true; - } - - if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) { - - _input._zone = z; - if (z->_flags & kFlagsNoWalk) { - // character doesn't need to walk to take specified action - _input._event = kEvAction; - - } else { - // action delayed: if Zone defined a moveto position the character is programmed to move there, - // else it will move to the mouse position - _input._event = kEvWalk; - _actionAfterWalk = true; - if (z->_moveTo.y != 0) { - _input._mousePos = z->_moveTo; - } - } - - beep(); - setArrowCursor(); - return true; - } - - return true; - -} - -bool Parallaction::translateInventoryInput() { - - if ((_engineFlags & kEngineInventory) == 0) { - return false; - } - - // in inventory - int16 _si = getHoverInventoryItem(_mousePos.x, _mousePos.y); - - if (_mouseButtons == kMouseRightUp) { - // right up hides inventory - - _input._event = kEvCloseInventory; - _input._inventoryIndex = getHoverInventoryItem(_mousePos.x, _mousePos.y); - highlightInventoryItem(_transCurrentHoverItem, 12); // disable - - if ((_engineFlags & kEngineDragging) == 0) { - return true; - } - - _engineFlags &= ~kEngineDragging; - ZonePtr z = hitZone(kZoneMerge, _activeItem._index, getInventoryItemIndex(_input._inventoryIndex)); - - if (z) { - dropItem(z->u.merge->_obj1); - dropItem(z->u.merge->_obj2); - addInventoryItem(z->u.merge->_obj3); - runCommands(z->_commands); - } - - return true; - } - - if (_si == _transCurrentHoverItem) { - _input._event = kEvNone; - return true; - } - - _transCurrentHoverItem = _si; - _input._event = kEvHoverInventory; - _input._inventoryIndex = _si; - return true; - -} - - -uint32 Parallaction::getElapsedTime() { - return g_system->getMillis() - _baseTime; -} - -void Parallaction::resetTimer() { - _baseTime = g_system->getMillis(); - return; -} - - -void Parallaction::waitTime(uint32 t) { - - uint32 v4 = 0; - - while (v4 < t * (1000 / 18.2)) { - v4 = getElapsedTime(); - } - - resetTimer(); - - return; -} - - -void Parallaction::showCursor(bool visible) { - _mouseHidden = !visible; - g_system->showMouse(visible); -} - - void Parallaction::freeCharacter() { debugC(1, kDebugExec, "freeCharacter()"); @@ -687,6 +278,102 @@ void Parallaction::showLocationComment(const char *text, bool end) { } +void Parallaction::processInput(InputData *data) { + + switch (data->_event) { + case kEvEnterZone: + debugC(2, kDebugInput, "processInput: kEvEnterZone"); + _gfx->setFloatingLabel(data->_label); + break; + + case kEvExitZone: + debugC(2, kDebugInput, "processInput: kEvExitZone"); + _gfx->setFloatingLabel(0); + break; + + case kEvAction: + debugC(2, kDebugInput, "processInput: kEvAction"); + _input->stopHovering(); + pauseJobs(); + runZone(data->_zone); + resumeJobs(); + break; + + case kEvOpenInventory: + _input->stopHovering(); + _gfx->setFloatingLabel(0); + if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) { + setArrowCursor(); + } + pauseJobs(); + openInventory(); + break; + + case kEvCloseInventory: // closes inventory and possibly select item + closeInventory(); + setInventoryCursor(data->_inventoryIndex); + resumeJobs(); + break; + + case kEvHoverInventory: + highlightInventoryItem(data->_inventoryIndex); // enable + break; + + case kEvWalk: + debugC(2, kDebugInput, "processInput: kEvWalk"); + _input->stopHovering(); + setArrowCursor(); + _char.scheduleWalk(data->_mousePos.x, data->_mousePos.y); + break; + + case kEvQuitGame: + _engineFlags |= kEngineQuit; + break; + + case kEvSaveGame: + _input->stopHovering(); + saveGame(); + setArrowCursor(); + break; + + case kEvLoadGame: + _input->stopHovering(); + loadGame(); + setArrowCursor(); + break; + + } + + return; +} + +void Parallaction::runGame() { + + InputData *data = _input->updateInput(); + if (data->_event != kEvNone) { + processInput(data); + } + + runPendingZones(); + + if (_engineFlags & kEngineChangeLocation) { + changeLocation(_location._name); + } + + + _gfx->beginFrame(); + + if (_input->_inputMode == Input::kInputModeGame) { + runScripts(); + walk(); + drawAnimations(); + } + + // change this to endFrame? + updateView(); + +} + @@ -719,15 +406,15 @@ void Parallaction::doLocationEnterTransition() { _gfx->updateScreen(); showLocationComment(_location._comment, false); - waitUntilLeftClick(); + _input->waitUntilLeftClick(); _gfx->freeBalloons(); // fades maximum intensity palette towards approximation of main palette for (uint16 _si = 0; _si<6; _si++) { pal.fadeTo(_gfx->_palette, 4); _gfx->setPalette(pal); - waitTime( 1 ); _gfx->updateScreen(); + g_system->delayMillis(20); } _gfx->setPalette(_gfx->_palette); diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 19ce437410..6e5957d3cd 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -33,6 +33,7 @@ #include "engines/engine.h" +#include "parallaction/input.h" #include "parallaction/inventory.h" #include "parallaction/parser.h" #include "parallaction/objects.h" @@ -96,14 +97,6 @@ enum { kPriority21 = 21 }; -enum { - kMouseNone = 0, - kMouseLeftUp = 1, - kMouseLeftDown = 2, - kMouseRightUp = 3, - kMouseRightDown = 4 -}; - enum EngineFlags { kEngineQuit = (1 << 0), kEnginePauseJobs = (1 << 1), @@ -151,7 +144,6 @@ extern char _password[8]; extern uint16 _score; extern uint16 _language; extern uint32 _engineFlags; -#define MAX_FORWARDS 50 extern char _saveData1[]; extern uint32 _commandFlags; extern const char *_dinoName; @@ -164,7 +156,6 @@ extern const char *_minidoughName; extern const char *_minidrkiName; -void waitUntilLeftClick(); @@ -172,7 +163,7 @@ void waitUntilLeftClick(); class Debugger; class Gfx; class SoundMan; - +class Input; struct Location { @@ -194,6 +185,7 @@ struct Location { // NS specific WalkNodeList _walkNodes; + char _slideText[2][MAX_TOKEN_LEN]; // BRA specific int _zeta0; @@ -246,13 +238,6 @@ public: - -#define DECLARE_UNQUALIFIED_ZONE_PARSER(sig) void locZoneParse_##sig() -#define DECLARE_UNQUALIFIED_ANIM_PARSER(sig) void locAnimParse_##sig() -#define DECLARE_UNQUALIFIED_COMMAND_PARSER(sig) void cmdParse_##sig() -#define DECLARE_UNQUALIFIED_LOCATION_PARSER(sig) void locParse_##sig() -#define DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sig) void instParse_##sig() - #define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op() #define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op() @@ -272,20 +257,7 @@ public: virtual bool loadGame() = 0; virtual bool saveGame() = 0; - uint16 readInput(); - void updateInput(); - - void waitTime(uint32 t); - - enum { - kInputModeGame = 0, - kInputModeComment = 1 - }; - - int _inputMode; - - void updateGameInput(); - void updateCommentInput(); + Input *_input; OpcodeSet _commandOpcodes; @@ -304,8 +276,7 @@ public: bool suspend; } _instRunCtxt; - - void showCursor(bool visible); + void processInput(InputData* data); void pauseJobs(); void resumeJobs(); @@ -331,13 +302,9 @@ public: Table *_globalTable; Table *_objectsNames; - Table *_zoneTypeNames; - Table *_zoneFlagNames; Table *_callableNames; Table *_localFlagNames; - Parser *_locationParser; - public: int getGameType() const; uint32 getFeatures() const; @@ -373,13 +340,6 @@ public: uint16 _numLocations; Location _location; - InventoryItem _activeItem; - - Common::Point _mousePos; - void getCursorPos(Common::Point& p) { - p = _mousePos; - } - ZonePtr _activeZone; @@ -390,52 +350,22 @@ public: Common::RandomSource _rnd; -protected: // data - Debugger *_debugger; - struct InputData { - uint16 _event; - Common::Point _mousePos; - int16 _inventoryIndex; - ZonePtr _zone; - Label* _label; - }; - - bool _mouseHidden; - - // input-only - InputData _input; - bool _actionAfterWalk; // actived when the character needs to move before taking an action - - // these two could/should be merged as they carry on the same duty in two member functions, - // respectively processInput and translateInput - int16 _procCurrentHoverItem; - int16 _transCurrentHoverItem; +protected: // data uint32 _baseTime; char _characterName1[50]; // only used in changeCharacter Common::String _saveFileName; - ZonePtr _hoverZone; - - protected: // members bool detectGame(void); void initGlobals(); void runGame(); void updateView(); - uint32 getElapsedTime(); - void resetTimer(); - - InputData *translateInput(); - bool translateGameInput(); - bool translateInventoryInput(); - void processInput(InputData*); - void scheduleLocationSwitch(const char *location); void doLocationEnterTransition(); @@ -472,13 +402,13 @@ public: void beep(); public: - const char **_zoneFlagNamesRes; - const char **_zoneTypeNamesRes; - const char **_commandsNamesRes; +// const char **_zoneFlagNamesRes; +// const char **_zoneTypeNamesRes; +// const char **_commandsNamesRes; const char **_callableNamesRes; const char **_instructionNamesRes; - void highlightInventoryItem(ItemPosition pos, byte color); + void highlightInventoryItem(ItemPosition pos); int16 getHoverInventoryItem(int16 x, int16 y); int addInventoryItem(ItemName item); int addInventoryItem(ItemName item, uint32 value); @@ -558,8 +488,12 @@ public: bool loadGame(); bool saveGame(); + void switchBackground(const char* background, const char* mask); private: + LocationParser_ns *_locationParser; + ProgramParser_ns *_programParser; + void initFonts(); void freeFonts(); void renameOldSavefiles(); @@ -586,9 +520,11 @@ private: void initResources(); void initCursors(); + void initParsers(); - static byte _mouseArrow[256]; - Frames *_mouseComposedArrow; + static byte _resMouseArrow[256]; + byte *_mouseArrow; + Frames *_mouseComposedArrow; static const Callable _dosCallables[25]; static const Callable _amigaCallables[25]; @@ -600,7 +536,6 @@ private: ZonePtr _moveSarcZone0; ZonePtr _moveSarcZone1; uint16 num_foglie; - char _slideText[2][MAX_TOKEN_LEN]; int16 _introSarcData1; uint16 _introSarcData2; // sarcophagus stuff to be saved uint16 _introSarcData3; // sarcophagus stuff to be saved @@ -649,149 +584,10 @@ protected: void walk(); void drawAnimations(); - - // location parser - OpcodeSet _locationParsers; - OpcodeSet _locationZoneParsers; - OpcodeSet _locationAnimParsers; - OpcodeSet _commandParsers; - Table *_commandsNames; - Table *_locationStmt; - Table *_locationZoneStmt; - Table *_locationAnimStmt; - - struct LocationParserContext { - bool end; - - const char *filename; - Script *script; - ZonePtr z; - AnimationPtr a; - int nextToken; - CommandList *list; - bool endcommands; - CommandPtr cmd; - - // BRA specific - int numZones; - char *bgName; - char *maskName; - char *pathName; - } _locParseCtxt; - - void warning_unexpected(); - - DECLARE_UNQUALIFIED_LOCATION_PARSER(endlocation); - DECLARE_UNQUALIFIED_LOCATION_PARSER(location); - DECLARE_UNQUALIFIED_LOCATION_PARSER(disk); - DECLARE_UNQUALIFIED_LOCATION_PARSER(nodes); - DECLARE_UNQUALIFIED_LOCATION_PARSER(zone); - DECLARE_UNQUALIFIED_LOCATION_PARSER(animation); - DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags); - DECLARE_UNQUALIFIED_LOCATION_PARSER(commands); - DECLARE_UNQUALIFIED_LOCATION_PARSER(acommands); - DECLARE_UNQUALIFIED_LOCATION_PARSER(flags); - DECLARE_UNQUALIFIED_LOCATION_PARSER(comment); - DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment); - DECLARE_UNQUALIFIED_LOCATION_PARSER(sound); - DECLARE_UNQUALIFIED_LOCATION_PARSER(music); - DECLARE_UNQUALIFIED_ZONE_PARSER(limits); - DECLARE_UNQUALIFIED_ZONE_PARSER(moveto); - DECLARE_UNQUALIFIED_ZONE_PARSER(type); - DECLARE_UNQUALIFIED_ZONE_PARSER(commands); - DECLARE_UNQUALIFIED_ZONE_PARSER(label); - DECLARE_UNQUALIFIED_ZONE_PARSER(flags); - DECLARE_UNQUALIFIED_ZONE_PARSER(endzone); - DECLARE_UNQUALIFIED_ZONE_PARSER(null); - DECLARE_UNQUALIFIED_ANIM_PARSER(script); - DECLARE_UNQUALIFIED_ANIM_PARSER(commands); - DECLARE_UNQUALIFIED_ANIM_PARSER(type); - DECLARE_UNQUALIFIED_ANIM_PARSER(label); - DECLARE_UNQUALIFIED_ANIM_PARSER(flags); - DECLARE_UNQUALIFIED_ANIM_PARSER(file); - DECLARE_UNQUALIFIED_ANIM_PARSER(position); - DECLARE_UNQUALIFIED_ANIM_PARSER(moveto); - DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation); - DECLARE_UNQUALIFIED_COMMAND_PARSER(flags); - DECLARE_UNQUALIFIED_COMMAND_PARSER(animation); - DECLARE_UNQUALIFIED_COMMAND_PARSER(zone); - DECLARE_UNQUALIFIED_COMMAND_PARSER(location); - DECLARE_UNQUALIFIED_COMMAND_PARSER(drop); - DECLARE_UNQUALIFIED_COMMAND_PARSER(call); - DECLARE_UNQUALIFIED_COMMAND_PARSER(simple); - DECLARE_UNQUALIFIED_COMMAND_PARSER(move); - DECLARE_UNQUALIFIED_COMMAND_PARSER(endcommands); - - virtual void parseGetData(Script &script, ZonePtr z); - virtual void parseExamineData(Script &script, ZonePtr z); - virtual void parseDoorData(Script &script, ZonePtr z); - virtual void parseMergeData(Script &script, ZonePtr z); - virtual void parseHearData(Script &script, ZonePtr z); - virtual void parseSpeakData(Script &script, ZonePtr z); - void parseLocation(const char *filename); - char *parseComment(Script &script); - char *parseDialogueString(Script &script); - Dialogue *parseDialogue(Script &script); - void resolveDialogueForwards(Dialogue *dialogue, uint numQuestions, Table &forwards); - Answer *parseAnswer(Script &script); - Question *parseQuestion(Script &script); - - void parseZone(Script &script, ZoneList &list, char *name); - void parseZoneTypeBlock(Script &script, ZonePtr z); - void parseWalkNodes(Script& script, WalkNodeList &list); - void parseAnimation(Script &script, AnimationList &list, char *name); - void parseCommands(Script &script, CommandList&); - void parseCommandFlags(); - void saveCommandForward(const char *name, CommandPtr cmd); - void resolveCommandForwards(); - void createCommand(uint id); - void addCommand(); - void initOpcodes(); - void initParsers(); - - struct CommandForwardReference { - char name[20]; - CommandPtr cmd; - } _forwardedCommands[MAX_FORWARDS]; - uint _numForwardedCommands; - - // program parser - OpcodeSet _instructionParsers; - Table *_instructionNames; - - struct { - bool end; - AnimationPtr a; - InstructionPtr inst; - LocalVariable *locals; - ProgramPtr program; - - // BRA specific - InstructionPtr openIf; - } _instParseCtxt; - - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(defLocal); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(animation); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(loop); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(x); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(y); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(z); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(f); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(inc); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(set); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(move); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(put); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(call); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sound); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(null); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endscript); - - void parseInstruction(ProgramPtr program); void loadProgram(AnimationPtr a, const char *filename); - void parseLValue(ScriptVar &var, const char *str); - virtual void parseRValue(ScriptVar &var, const char *str); - void wrapLocalVar(LocalVariable *local); + + void initOpcodes(); DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid); DECLARE_UNQUALIFIED_COMMAND_OPCODE(set); @@ -837,7 +633,6 @@ protected: uint16 guiSelectGame(); int guiGetSelectedBlock(const Common::Point &p); - void switchBackground(const char* background, const char* mask); void showSlide(const char *name); }; @@ -859,11 +654,11 @@ public: public: typedef void (Parallaction_br::*Callable)(void*); virtual void callFunction(uint index, void* parm); + void changeCharacter(const char *name); public: Table *_countersNames; - Table *_audioCommandsNames; const char **_audioCommandsNamesRes; int _part; @@ -881,6 +676,9 @@ public: uint32 _zoneFlags[NUM_LOCATIONS][NUM_ZONES]; private: + LocationParser_br *_locationParser; + ProgramParser_br *_programParser; + void initResources(); void initFonts(); void freeFonts(); @@ -891,7 +689,6 @@ private: void setInventoryCursor(int pos); void changeLocation(char *location); - void changeCharacter(const char *name); void runPendingZones(); void initPart(); @@ -925,48 +722,8 @@ private: const Callable *_callables; - DECLARE_UNQUALIFIED_LOCATION_PARSER(location); - DECLARE_UNQUALIFIED_LOCATION_PARSER(zone); - DECLARE_UNQUALIFIED_LOCATION_PARSER(animation); - DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags); - DECLARE_UNQUALIFIED_LOCATION_PARSER(flags); - DECLARE_UNQUALIFIED_LOCATION_PARSER(comment); - DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment); - DECLARE_UNQUALIFIED_LOCATION_PARSER(sound); - DECLARE_UNQUALIFIED_LOCATION_PARSER(music); - DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant); - DECLARE_UNQUALIFIED_LOCATION_PARSER(ifchar); - DECLARE_UNQUALIFIED_LOCATION_PARSER(character); - DECLARE_UNQUALIFIED_LOCATION_PARSER(mask); - DECLARE_UNQUALIFIED_LOCATION_PARSER(path); - DECLARE_UNQUALIFIED_LOCATION_PARSER(escape); - DECLARE_UNQUALIFIED_LOCATION_PARSER(zeta); - DECLARE_UNQUALIFIED_LOCATION_PARSER(null); - DECLARE_UNQUALIFIED_COMMAND_PARSER(ifchar); - DECLARE_UNQUALIFIED_COMMAND_PARSER(endif); - DECLARE_UNQUALIFIED_COMMAND_PARSER(location); - DECLARE_UNQUALIFIED_COMMAND_PARSER(toggle); - DECLARE_UNQUALIFIED_COMMAND_PARSER(string); - DECLARE_UNQUALIFIED_COMMAND_PARSER(math); - DECLARE_UNQUALIFIED_COMMAND_PARSER(test); - DECLARE_UNQUALIFIED_COMMAND_PARSER(music); - DECLARE_UNQUALIFIED_COMMAND_PARSER(zeta); - DECLARE_UNQUALIFIED_COMMAND_PARSER(swap); - DECLARE_UNQUALIFIED_COMMAND_PARSER(give); - DECLARE_UNQUALIFIED_COMMAND_PARSER(text); - DECLARE_UNQUALIFIED_COMMAND_PARSER(unary); - void parseLocation(const char* name); - - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(zone); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(color); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(mask); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(print); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(text); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(if_op); - DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endif); - - virtual void parseRValue(ScriptVar &var, const char *str); + void loadProgram(AnimationPtr a, const char *filename); DECLARE_UNQUALIFIED_COMMAND_OPCODE(location); DECLARE_UNQUALIFIED_COMMAND_OPCODE(open); @@ -1003,13 +760,6 @@ private: DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret); DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave); DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave); - DECLARE_UNQUALIFIED_ZONE_PARSER(limits); - DECLARE_UNQUALIFIED_ZONE_PARSER(moveto); - DECLARE_UNQUALIFIED_ZONE_PARSER(type); - DECLARE_UNQUALIFIED_ANIM_PARSER(file); - DECLARE_UNQUALIFIED_ANIM_PARSER(position); - DECLARE_UNQUALIFIED_ANIM_PARSER(moveto); - DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation); DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on); DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off); diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 29e9fe6d70..0f5cc2a0c4 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -27,6 +27,7 @@ #include "common/util.h" #include "parallaction/parallaction.h" +#include "parallaction/input.h" #include "parallaction/sound.h" namespace Parallaction { @@ -72,7 +73,10 @@ int Parallaction_br::init() { initFonts(); initCursors(); initOpcodes(); - initParsers(); + _locationParser = new LocationParser_br(this); + _locationParser->init(); + _programParser = new ProgramParser_br(this); + _programParser->init(); _part = -1; @@ -107,7 +111,7 @@ int Parallaction_br::go() { // initCharacter(); - _inputMode = kInputModeGame; + _input->_inputMode = Input::kInputModeGame; while ((_engineFlags & (kEngineReturn | kEngineQuit)) == 0) { runGame(); } @@ -198,7 +202,7 @@ void Parallaction_br::runPendingZones() { if (_activeZone) { z = _activeZone; // speak Zone or sound _activeZone = nullZonePtr; -// runZone(z); // FIXME: BRA doesn't handle sound yet + runZone(z); // FIXME: BRA doesn't handle sound yet } if (_activeZone2) { @@ -233,8 +237,57 @@ void Parallaction_br::changeLocation(char *location) { _engineFlags &= ~kEngineChangeLocation; } + +// FIXME: Parallaction_br::parseLocation() is now a verbatim copy of the same routine from Parallaction_ns. +void Parallaction_br::parseLocation(const char *filename) { + debugC(1, kDebugParser, "parseLocation('%s')", filename); + + allocateLocationSlot(filename); + Script *script = _disk->loadLocation(filename); + + _locationParser->parse(script); + delete script; + + // this loads animation scripts + AnimationList::iterator it = _vm->_location._animations.begin(); + for ( ; it != _vm->_location._animations.end(); it++) { + if ((*it)->_scriptName) { + loadProgram(*it, (*it)->_scriptName); + } + } + + debugC(1, kDebugParser, "parseLocation('%s') done", filename); + return; +} + +void Parallaction_br::loadProgram(AnimationPtr a, const char *filename) { + debugC(1, kDebugParser, "loadProgram(Animation: %s, script: %s)", a->_name, filename); + + Script *script = _disk->loadScript(filename); + ProgramPtr program(new Program); + program->_anim = a; + + _programParser->parse(script, program); + + delete script; + + _vm->_location._programs.push_back(program); + + debugC(1, kDebugParser, "loadProgram() done"); + + return; +} + + + void Parallaction_br::changeCharacter(const char *name) { + const char *charName = _char.getName(); + if (!scumm_stricmp(charName, name)) { + return; + } + _char.setName(name); + _char._talk = _disk->loadTalk(name); } diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index 7a476f7d24..2cca3a6a4a 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -28,6 +28,7 @@ #include "common/config-manager.h" #include "parallaction/parallaction.h" +#include "parallaction/input.h" #include "parallaction/sound.h" @@ -135,7 +136,10 @@ int Parallaction_ns::init() { initFonts(); initCursors(); initOpcodes(); - initParsers(); + _locationParser = new LocationParser_ns(this); + _locationParser->init(); + _programParser = new ProgramParser_ns(this); + _programParser->init(); _introSarcData1 = 0; _introSarcData2 = 1; @@ -155,10 +159,6 @@ Parallaction_ns::~Parallaction_ns() { delete _mouseComposedArrow; - delete _commandsNames; - delete _instructionNames; - delete _locationStmt; - _location._animations.remove(_char._ani); } @@ -174,18 +174,8 @@ void Parallaction_ns::freeFonts() { } void Parallaction_ns::initCursors() { - _mouseComposedArrow = _disk->loadPointer("pointer"); - - byte temp[MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT]; - memcpy(temp, _mouseArrow, MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT); - - uint16 k = 0; - for (uint16 i = 0; i < 4; i++) { - for (uint16 j = 0; j < 64; j++) _mouseArrow[k++] = temp[i + j * 4]; - } - - return; + _mouseArrow = _resMouseArrow; } void Parallaction_ns::setArrowCursor() { @@ -194,7 +184,7 @@ void Parallaction_ns::setArrowCursor() { // this stuff is needed to avoid artifacts with labels and selected items when switching cursors _gfx->setFloatingLabel(0); - _activeItem._id = 0; + _input->_activeItem._id = 0; _system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0); _system->showMouse(true); @@ -210,7 +200,7 @@ void Parallaction_ns::setInventoryCursor(int pos) { if (item->_index == 0) return; - _activeItem._id = item->_id; + _input->_activeItem._id = item->_id; byte *v8 = _mouseComposedArrow->getData(0); @@ -246,7 +236,7 @@ int Parallaction_ns::go() { changeLocation(_location._name); - _inputMode = kInputModeGame; + _input->_inputMode = Input::kInputModeGame; while ((_engineFlags & kEngineQuit) == 0) { runGame(); } @@ -301,7 +291,7 @@ void Parallaction_ns::changeLocation(char *location) { _gfx->setFloatingLabel(0); _gfx->freeLabels(); - _hoverZone = nullZonePtr; + _input->stopHovering(); if (_engineFlags & kEngineBlockInput) { setArrowCursor(); } @@ -315,9 +305,9 @@ void Parallaction_ns::changeLocation(char *location) { if (locname.hasSlide()) { showSlide(locname.slide()); - uint id = _gfx->createLabel(_menuFont, _slideText[0], 1); + uint id = _gfx->createLabel(_menuFont, _location._slideText[0], 1); _gfx->showLabel(id, CENTER_LABEL_HORIZONTAL, 14); - waitUntilLeftClick(); + _input->waitUntilLeftClick(); _gfx->freeLabels(); freeBackground(); } @@ -367,6 +357,34 @@ void Parallaction_ns::changeLocation(char *location) { } +void Parallaction_ns::parseLocation(const char *filename) { + debugC(1, kDebugParser, "parseLocation('%s')", filename); + + allocateLocationSlot(filename); + Script *script = _disk->loadLocation(filename); + + // TODO: the following two lines are specific to Nippon Safes + // and should be moved into something like 'initializeParsing()' + _vm->_location._hasSound = false; + + _locationParser->parse(script); + + delete script; + + // this loads animation scripts + AnimationList::iterator it = _vm->_location._animations.begin(); + for ( ; it != _vm->_location._animations.end(); it++) { + if ((*it)->_scriptName) { + loadProgram(*it, (*it)->_scriptName); + } + } + + debugC(1, kDebugParser, "parseLocation('%s') done", filename); + return; +} + + + void Parallaction_ns::changeCharacter(const char *name) { debugC(1, kDebugExec, "changeCharacter(%s)", name); diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp index 665da16636..f9de6eb4af 100644 --- a/engines/parallaction/parser.cpp +++ b/engines/parallaction/parser.cpp @@ -213,7 +213,9 @@ uint16 Script::readLineToken(bool errorOnEOF) { void Parser::reset() { _currentOpcodes = 0; _currentStatements = 0; - _script = 0; + + _statements.clear(); + _opcodes.clear(); } void Parser::pushTables(OpcodeSet *opcodes, Table *statements) { @@ -234,7 +236,6 @@ void Parser::popTables() { void Parser::parseStatement() { assert(_currentOpcodes != 0); - _script->readLineToken(true); _lookup = _currentStatements->lookup(_tokens[0]); debugC(9, kDebugParser, "parseStatement: %s (lookup = %i)", _tokens[0], _lookup); @@ -242,14 +243,5 @@ void Parser::parseStatement() { (*(*_currentOpcodes)[_lookup])(); } -void Parser::bind(Script *script) { - reset(); - _script = script; -} - -void Parser::unbind() { - reset(); -} - } // namespace Parallaction diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h index d29a6c7e73..d488cf9b58 100644 --- a/engines/parallaction/parser.h +++ b/engines/parallaction/parser.h @@ -28,6 +28,7 @@ #include "common/stream.h" #include "parallaction/objects.h" +#include "parallaction/walk.h" namespace Parallaction { @@ -58,66 +59,347 @@ public: }; +typedef Common::Functor0<void> Opcode; +typedef Common::Array<const Opcode*> OpcodeSet; + -class Opcode { +class Parser { public: - virtual void operator()() const = 0; - virtual ~Opcode() { } + Parser() { reset(); } + ~Parser() {} + + uint _lookup; + + Common::Stack<OpcodeSet*> _opcodes; + Common::Stack<Table*> _statements; + + OpcodeSet *_currentOpcodes; + Table *_currentStatements; + + void reset(); + void pushTables(OpcodeSet *opcodes, Table* statements); + void popTables(); + void parseStatement(); + }; -template <class T> -class OpcodeImpl : public Opcode { +#define DECLARE_UNQUALIFIED_ZONE_PARSER(sig) void locZoneParse_##sig() +#define DECLARE_UNQUALIFIED_ANIM_PARSER(sig) void locAnimParse_##sig() +#define DECLARE_UNQUALIFIED_COMMAND_PARSER(sig) void cmdParse_##sig() +#define DECLARE_UNQUALIFIED_LOCATION_PARSER(sig) void locParse_##sig() +#define DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sig) void instParse_##sig() - typedef void (T::*Fn)(); +#define MAX_FORWARDS 50 - T* _instance; - Fn _fn; +class Parallaction_ns; +class Parallaction_br; + +class LocationParser_ns { + +protected: + Parallaction_ns* _vm; + Script *_script; + Parser *_parser; + + Table *_zoneTypeNames; + Table *_zoneFlagNames; + + // location parser + OpcodeSet _locationParsers; + OpcodeSet _locationZoneParsers; + OpcodeSet _locationAnimParsers; + OpcodeSet _commandParsers; + Table *_commandsNames; + Table *_locationStmt; + Table *_locationZoneStmt; + Table *_locationAnimStmt; + + struct ParserContext { + bool end; + + const char *filename; + ZonePtr z; + AnimationPtr a; + int nextToken; + CommandList *list; + bool endcommands; + CommandPtr cmd; + + // BRA specific + int numZones; + char *bgName; + char *maskName; + char *pathName; + char *characterName; + } ctxt; + + void warning_unexpected(); + + DECLARE_UNQUALIFIED_LOCATION_PARSER(endlocation); + DECLARE_UNQUALIFIED_LOCATION_PARSER(location); + DECLARE_UNQUALIFIED_LOCATION_PARSER(disk); + DECLARE_UNQUALIFIED_LOCATION_PARSER(nodes); + DECLARE_UNQUALIFIED_LOCATION_PARSER(zone); + DECLARE_UNQUALIFIED_LOCATION_PARSER(animation); + DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags); + DECLARE_UNQUALIFIED_LOCATION_PARSER(commands); + DECLARE_UNQUALIFIED_LOCATION_PARSER(acommands); + DECLARE_UNQUALIFIED_LOCATION_PARSER(flags); + DECLARE_UNQUALIFIED_LOCATION_PARSER(comment); + DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment); + DECLARE_UNQUALIFIED_LOCATION_PARSER(sound); + DECLARE_UNQUALIFIED_LOCATION_PARSER(music); + DECLARE_UNQUALIFIED_ZONE_PARSER(limits); + DECLARE_UNQUALIFIED_ZONE_PARSER(moveto); + DECLARE_UNQUALIFIED_ZONE_PARSER(type); + DECLARE_UNQUALIFIED_ZONE_PARSER(commands); + DECLARE_UNQUALIFIED_ZONE_PARSER(label); + DECLARE_UNQUALIFIED_ZONE_PARSER(flags); + DECLARE_UNQUALIFIED_ZONE_PARSER(endzone); + DECLARE_UNQUALIFIED_ZONE_PARSER(null); + DECLARE_UNQUALIFIED_ANIM_PARSER(script); + DECLARE_UNQUALIFIED_ANIM_PARSER(commands); + DECLARE_UNQUALIFIED_ANIM_PARSER(type); + DECLARE_UNQUALIFIED_ANIM_PARSER(label); + DECLARE_UNQUALIFIED_ANIM_PARSER(flags); + DECLARE_UNQUALIFIED_ANIM_PARSER(file); + DECLARE_UNQUALIFIED_ANIM_PARSER(position); + DECLARE_UNQUALIFIED_ANIM_PARSER(moveto); + DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation); + DECLARE_UNQUALIFIED_COMMAND_PARSER(flags); + DECLARE_UNQUALIFIED_COMMAND_PARSER(animation); + DECLARE_UNQUALIFIED_COMMAND_PARSER(zone); + DECLARE_UNQUALIFIED_COMMAND_PARSER(location); + DECLARE_UNQUALIFIED_COMMAND_PARSER(drop); + DECLARE_UNQUALIFIED_COMMAND_PARSER(call); + DECLARE_UNQUALIFIED_COMMAND_PARSER(simple); + DECLARE_UNQUALIFIED_COMMAND_PARSER(move); + DECLARE_UNQUALIFIED_COMMAND_PARSER(endcommands); + + virtual void parseGetData(ZonePtr z); + virtual void parseExamineData(ZonePtr z); + virtual void parseDoorData(ZonePtr z); + virtual void parseMergeData(ZonePtr z); + virtual void parseHearData(ZonePtr z); + virtual void parseSpeakData(ZonePtr z); + + char *parseComment(); + char *parseDialogueString(); + Dialogue *parseDialogue(); + void resolveDialogueForwards(Dialogue *dialogue, uint numQuestions, Table &forwards); + Answer *parseAnswer(); + Question *parseQuestion(); + + void parseZone(ZoneList &list, char *name); + void parseZoneTypeBlock(ZonePtr z); + void parseWalkNodes(WalkNodeList &list); + void parseAnimation(AnimationList &list, char *name); + void parseCommands(CommandList&); + void parseCommandFlags(); + void saveCommandForward(const char *name, CommandPtr cmd); + void resolveCommandForwards(); + void createCommand(uint id); + void addCommand(); + + struct CommandForwardReference { + char name[20]; + CommandPtr cmd; + } _forwardedCommands[MAX_FORWARDS]; + uint _numForwardedCommands; + + void clearSet(OpcodeSet &opcodes) { + for (Common::Array<const Opcode*>::iterator i = opcodes.begin(); i != opcodes.end(); ++i) + delete *i; + opcodes.clear(); + } public: - OpcodeImpl(T* instance, const Fn &fn) : _instance(instance), _fn(fn) { } + LocationParser_ns(Parallaction_ns *vm) : _vm(vm) { + } + + virtual void init(); + + virtual ~LocationParser_ns() { + delete _commandsNames; + delete _locationStmt; + delete _zoneTypeNames; + delete _zoneFlagNames; + + delete _parser; - void operator()() const { - (_instance->*_fn)(); + clearSet(_commandParsers); + clearSet(_locationAnimParsers); + clearSet(_locationZoneParsers); + clearSet(_locationParsers); } -}; + void parse(Script *script); -typedef Common::Array<const Opcode*> OpcodeSet; +}; +class LocationParser_br : public LocationParser_ns { -class Parser { +protected: + Table *_audioCommandsNames; + + Parallaction_br* _vm; + + DECLARE_UNQUALIFIED_LOCATION_PARSER(location); + DECLARE_UNQUALIFIED_LOCATION_PARSER(zone); + DECLARE_UNQUALIFIED_LOCATION_PARSER(animation); + DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags); + DECLARE_UNQUALIFIED_LOCATION_PARSER(flags); + DECLARE_UNQUALIFIED_LOCATION_PARSER(comment); + DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment); + DECLARE_UNQUALIFIED_LOCATION_PARSER(sound); + DECLARE_UNQUALIFIED_LOCATION_PARSER(music); + DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant); + DECLARE_UNQUALIFIED_LOCATION_PARSER(ifchar); + DECLARE_UNQUALIFIED_LOCATION_PARSER(character); + DECLARE_UNQUALIFIED_LOCATION_PARSER(mask); + DECLARE_UNQUALIFIED_LOCATION_PARSER(path); + DECLARE_UNQUALIFIED_LOCATION_PARSER(escape); + DECLARE_UNQUALIFIED_LOCATION_PARSER(zeta); + DECLARE_UNQUALIFIED_LOCATION_PARSER(null); + DECLARE_UNQUALIFIED_COMMAND_PARSER(ifchar); + DECLARE_UNQUALIFIED_COMMAND_PARSER(endif); + DECLARE_UNQUALIFIED_COMMAND_PARSER(location); + DECLARE_UNQUALIFIED_COMMAND_PARSER(toggle); + DECLARE_UNQUALIFIED_COMMAND_PARSER(string); + DECLARE_UNQUALIFIED_COMMAND_PARSER(math); + DECLARE_UNQUALIFIED_COMMAND_PARSER(test); + DECLARE_UNQUALIFIED_COMMAND_PARSER(music); + DECLARE_UNQUALIFIED_COMMAND_PARSER(zeta); + DECLARE_UNQUALIFIED_COMMAND_PARSER(swap); + DECLARE_UNQUALIFIED_COMMAND_PARSER(give); + DECLARE_UNQUALIFIED_COMMAND_PARSER(text); + DECLARE_UNQUALIFIED_COMMAND_PARSER(unary); + DECLARE_UNQUALIFIED_ZONE_PARSER(limits); + DECLARE_UNQUALIFIED_ZONE_PARSER(moveto); + DECLARE_UNQUALIFIED_ZONE_PARSER(type); + DECLARE_UNQUALIFIED_ANIM_PARSER(file); + DECLARE_UNQUALIFIED_ANIM_PARSER(position); + DECLARE_UNQUALIFIED_ANIM_PARSER(moveto); + DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation); public: - Parser() { reset(); } - ~Parser() {} + LocationParser_br(Parallaction_br *vm) : LocationParser_ns((Parallaction_ns*)vm), _vm(vm) { + } - uint _lookup; + virtual void init(); - Common::Stack<OpcodeSet*> _opcodes; - Common::Stack<Table*> _statements; + virtual ~LocationParser_br() { + delete _commandsNames; + delete _locationStmt; + } - OpcodeSet *_currentOpcodes; - Table *_currentStatements; + void parse(Script *script); + +}; - void bind(Script *script); - void unbind(); - void pushTables(OpcodeSet *opcodes, Table* statements); - void popTables(); - void parseStatement(); + + +class ProgramParser_ns { protected: - void reset(); + Parser *_parser; + Parallaction_ns *_vm; Script *_script; + ProgramPtr _program; + + // program parser + OpcodeSet _instructionParsers; + Table *_instructionNames; + + struct ParserContext { + bool end; + AnimationPtr a; + InstructionPtr inst; + LocalVariable *locals; + + // BRA specific + InstructionPtr openIf; + } ctxt; + + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(defLocal); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(animation); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(loop); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(x); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(y); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(z); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(f); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(inc); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(set); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(move); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(put); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(call); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sound); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(null); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endscript); + + void parseInstruction(); + void parseLValue(ScriptVar &var, const char *str); + virtual void parseRValue(ScriptVar &var, const char *str); + + void clearSet(OpcodeSet &opcodes) { + for (Common::Array<const Opcode*>::iterator i = opcodes.begin(); i != opcodes.end(); ++i) + delete *i; + opcodes.clear(); + } + +public: + ProgramParser_ns(Parallaction_ns *vm) : _vm(vm) { + } + + virtual void init(); + + virtual ~ProgramParser_ns() { + delete _instructionNames; + clearSet(_instructionParsers); + } + + void parse(Script *script, ProgramPtr program); + }; +class ProgramParser_br : public ProgramParser_ns { + +protected: + Parallaction_br *_vm; + + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(zone); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(color); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(mask); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(print); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(text); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(if_op); + DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endif); + + virtual void parseRValue(ScriptVar &var, const char *str); + +public: + ProgramParser_br(Parallaction_br *vm) : ProgramParser_ns((Parallaction_ns*)vm), _vm(vm) { + } + + virtual void init(); + virtual ~ProgramParser_br() { + delete _instructionNames; + delete _parser; + } + +}; } // namespace Parallaction #endif + + + + diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp index 2544267382..51da7eb396 100644 --- a/engines/parallaction/parser_br.cpp +++ b/engines/parallaction/parser_br.cpp @@ -104,18 +104,217 @@ namespace Parallaction { #define INST_ENDIF 30 #define INST_STOP 31 -#define DECLARE_ZONE_PARSER(sig) void Parallaction_br::locZoneParse_##sig() -#define DECLARE_ANIM_PARSER(sig) void Parallaction_br::locAnimParse_##sig() -#define DECLARE_COMMAND_PARSER(sig) void Parallaction_br::cmdParse_##sig() -#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction_br::instParse_##sig() -#define DECLARE_LOCATION_PARSER(sig) void Parallaction_br::locParse_##sig() +const char *_zoneTypeNamesRes_br[] = { + "examine", + "door", + "get", + "merge", + "taste", + "hear", + "feel", + "speak", + "none", + "trap", + "you", + "command", + "path", + "box" +}; + +const char *_zoneFlagNamesRes_br[] = { + "closed", + "active", + "remove", + "acting", + "locked", + "fixed", + "noname", + "nomasked", + "looping", + "added", + "character", + "nowalk", + "yourself", + "scaled", + "selfuse" +}; + +const char *_commandsNamesRes_br[] = { + "set", + "clear", + "start", + "speak", + "get", + "location", + "open", + "close", + "on", + "off", + "call", + "toggle", + "drop", + "quit", + "move", + "stop", + "character", + "followme", + "onmouse", + "offmouse", + "add", + "leave", + "inc", + "dec", + "test", + "dummy", + "dummy", + "let", + "music", + "fix", + "unfix", + "zeta", + "scroll", + "swap", + "give", + "text", + "part", + "dummy", + "return", + "onsave", + "offsave", + "endcommands", + "ifchar", + "endif" +}; + + +const char *_audioCommandsNamesRes_br[] = { + "play", + "stop", + "pause", + "channel_level", + "fadein", + "fadeout", + "volume", + " ", + "faderate", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "loop" +}; + +const char *_locationStmtRes_br[] = { + "character", + "endlocation", + "ifchar", + "endif", + "location", + "mask", + "path", + "disk", + "localflags", + "commands", + "escape", + "acommands", + "flags", + "comment", + "endcomment", + "zone", + "animation", + "zeta", + "music", + "sound" +}; + +const char *_locationZoneStmtRes_br[] = { + "endzone", + "limits", + "moveto", + "type", + "commands", + "label", + "flags" +}; + +const char *_locationAnimStmtRes_br[] = { + "endanimation", + "endzone", + "script", + "commands", + "type", + "label", + "flags", + "file", + "position", + "moveto" +}; + +const char *_instructionNamesRes_br[] = { + "on", + "off", + "x", + "y", + "z", + "f", + "loop", + "endloop", + "show", + "inc", + "dec", + "set", + "put", + "call", + "wait", + "start", + "process", + "move", + "color", + "sound", + "mask", + "print", + "text", + "mul", + "div", + "if", + "dummy", + "dummy", + "endif", + "stop", + "endscript" +}; + + +#define SetOpcodeTable(x) table = &x; + +typedef Common::Functor0Mem<void, ProgramParser_br> OpcodeV1; +#define INSTRUCTION_PARSER(sig) table->push_back(new OpcodeV1(this, &ProgramParser_br::instParse_##sig)) + +typedef Common::Functor0Mem<void, LocationParser_br> OpcodeV2; +#define ZONE_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_br::locZoneParse_##sig)) +#define ANIM_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_br::locAnimParse_##sig)) +#define LOCATION_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_br::locParse_##sig)) +#define COMMAND_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_br::cmdParse_##sig)) + +#define WARNING_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_br::warning_##sig)) + + +#define DECLARE_ZONE_PARSER(sig) void LocationParser_br::locZoneParse_##sig() +#define DECLARE_ANIM_PARSER(sig) void LocationParser_br::locAnimParse_##sig() +#define DECLARE_COMMAND_PARSER(sig) void LocationParser_br::cmdParse_##sig() +#define DECLARE_LOCATION_PARSER(sig) void LocationParser_br::locParse_##sig() + +#define DECLARE_INSTRUCTION_PARSER(sig) void ProgramParser_br::instParse_##sig() DECLARE_LOCATION_PARSER(location) { debugC(7, kDebugParser, "LOCATION_PARSER(location) "); - strcpy(_location._name, _tokens[1]); - _locParseCtxt.bgName = strdup(_tokens[1]); + strcpy(_vm->_location._name, _tokens[1]); + ctxt.bgName = strdup(_tokens[1]); bool flip = false; int nextToken; @@ -130,14 +329,14 @@ DECLARE_LOCATION_PARSER(location) { // TODO: handle background horizontal flip (via a context parameter) if (_tokens[nextToken][0] != '\0') { - _char._ani->_left = atoi(_tokens[nextToken]); + _vm->_char._ani->_left = atoi(_tokens[nextToken]); nextToken++; - _char._ani->_top = atoi(_tokens[nextToken]); + _vm->_char._ani->_top = atoi(_tokens[nextToken]); nextToken++; } if (_tokens[nextToken][0] != '\0') { - _char._ani->_frame = atoi(_tokens[nextToken]); + _vm->_char._ani->_frame = atoi(_tokens[nextToken]); } } @@ -146,14 +345,14 @@ DECLARE_LOCATION_PARSER(location) { DECLARE_LOCATION_PARSER(zone) { debugC(7, kDebugParser, "LOCATION_PARSER(zone) "); - parseZone(*_locParseCtxt.script, _location._zones, _tokens[1]); + parseZone(_vm->_location._zones, _tokens[1]); - _locParseCtxt.z->_index = _locParseCtxt.numZones++; + ctxt.z->_index = ctxt.numZones++; - if (getLocationFlags() & kFlagsVisited) { - _locParseCtxt.z->_flags = _zoneFlags[_currentLocationIndex][_locParseCtxt.z->_index]; + if (_vm->getLocationFlags() & kFlagsVisited) { + ctxt.z->_flags = _vm->_zoneFlags[_vm->_currentLocationIndex][ctxt.z->_index]; } else { - _zoneFlags[_currentLocationIndex][_locParseCtxt.z->_index] = _locParseCtxt.z->_flags; + _vm->_zoneFlags[_vm->_currentLocationIndex][ctxt.z->_index] = ctxt.z->_flags; } } @@ -162,14 +361,14 @@ DECLARE_LOCATION_PARSER(zone) { DECLARE_LOCATION_PARSER(animation) { debugC(7, kDebugParser, "LOCATION_PARSER(animation) "); - parseAnimation(*_locParseCtxt.script, _location._animations, _tokens[1]); + parseAnimation(_vm->_location._animations, _tokens[1]); - _locParseCtxt.a->_index = _locParseCtxt.numZones++; + ctxt.a->_index = ctxt.numZones++; - if (getLocationFlags() & kFlagsVisited) { - _locParseCtxt.a->_flags = _zoneFlags[_currentLocationIndex][_locParseCtxt.a->_index]; + if (_vm->getLocationFlags() & kFlagsVisited) { + ctxt.a->_flags = _vm->_zoneFlags[_vm->_currentLocationIndex][ctxt.a->_index]; } else { - _zoneFlags[_currentLocationIndex][_locParseCtxt.a->_index] = _locParseCtxt.a->_flags; + _vm->_zoneFlags[_vm->_currentLocationIndex][ctxt.a->_index] = ctxt.a->_flags; } } @@ -180,7 +379,7 @@ DECLARE_LOCATION_PARSER(localflags) { int _si = 1; while (_tokens[_si][0] != '\0') { - _localFlagNames->addData(_tokens[_si]); + _vm->_localFlagNames->addData(_tokens[_si]); _si++; } } @@ -189,14 +388,14 @@ DECLARE_LOCATION_PARSER(localflags) { DECLARE_LOCATION_PARSER(flags) { debugC(7, kDebugParser, "LOCATION_PARSER(flags) "); - if ((getLocationFlags() & kFlagsVisited) == 0) { + if ((_vm->getLocationFlags() & kFlagsVisited) == 0) { // only for 1st visit - clearLocationFlags(kFlagsAll); + _vm->clearLocationFlags(kFlagsAll); int _si = 1; do { - byte _al = _localFlagNames->lookup(_tokens[_si]); - setLocationFlags(1 << (_al - 1)); + byte _al = _vm->_localFlagNames->lookup(_tokens[_si]); + _vm->setLocationFlags(1 << (_al - 1)); _si++; if (scumm_stricmp(_tokens[_si], "|")) break; @@ -209,14 +408,14 @@ DECLARE_LOCATION_PARSER(flags) { DECLARE_LOCATION_PARSER(comment) { debugC(7, kDebugParser, "LOCATION_PARSER(comment) "); - _location._comment = parseComment(*_locParseCtxt.script); + _vm->_location._comment = parseComment(); } DECLARE_LOCATION_PARSER(endcomment) { debugC(7, kDebugParser, "LOCATION_PARSER(endcomment) "); - _location._endComment = parseComment(*_locParseCtxt.script); + _vm->_location._endComment = parseComment(); } @@ -236,21 +435,21 @@ DECLARE_LOCATION_PARSER(music) { DECLARE_LOCATION_PARSER(redundant) { debugC(7, kDebugParser, "LOCATION_PARSER(redundant) "); - warning("redundant '%s' line found in script '%s'", _tokens[0], _locParseCtxt.filename); + warning("redundant '%s' line found in script '%s'", _tokens[0], ctxt.filename); } DECLARE_LOCATION_PARSER(character) { debugC(7, kDebugParser, "LOCATION_PARSER(character) "); -// changeCharacter(character); + ctxt.characterName = strdup(_tokens[0]); } DECLARE_LOCATION_PARSER(ifchar) { debugC(7, kDebugParser, "LOCATION_PARSER(ifchar) "); - _locParseCtxt.script->skip("ENDIF"); + _script->skip("ENDIF"); } @@ -264,45 +463,45 @@ DECLARE_LOCATION_PARSER(null) { DECLARE_LOCATION_PARSER(mask) { debugC(7, kDebugParser, "LOCATION_PARSER(mask) "); - _locParseCtxt.maskName = strdup(_tokens[1]); - _gfx->_backgroundInfo.layers[0] = atoi(_tokens[2]); - _gfx->_backgroundInfo.layers[1] = atoi(_tokens[3]); - _gfx->_backgroundInfo.layers[2] = atoi(_tokens[4]); + ctxt.maskName = strdup(_tokens[1]); + _vm->_gfx->_backgroundInfo.layers[0] = atoi(_tokens[2]); + _vm->_gfx->_backgroundInfo.layers[1] = atoi(_tokens[3]); + _vm->_gfx->_backgroundInfo.layers[2] = atoi(_tokens[4]); } DECLARE_LOCATION_PARSER(path) { debugC(7, kDebugParser, "LOCATION_PARSER(path) "); - _locParseCtxt.pathName = strdup(_tokens[1]); + ctxt.pathName = strdup(_tokens[1]); } DECLARE_LOCATION_PARSER(escape) { debugC(7, kDebugParser, "LOCATION_PARSER(escape) "); - parseCommands(*_locParseCtxt.script, _location._escapeCommands); + parseCommands(_vm->_location._escapeCommands); } DECLARE_LOCATION_PARSER(zeta) { debugC(7, kDebugParser, "LOCATION_PARSER(zeta) "); - _location._zeta0 = atoi(_tokens[1]); - _location._zeta1 = atoi(_tokens[2]); + _vm->_location._zeta0 = atoi(_tokens[1]); + _vm->_location._zeta1 = atoi(_tokens[2]); if (_tokens[3][0] != '\0') { - _location._zeta2 = atoi(_tokens[1]); + _vm->_location._zeta2 = atoi(_tokens[1]); } else { - _location._zeta2 = 50; + _vm->_location._zeta2 = 50; } } DECLARE_COMMAND_PARSER(ifchar) { debugC(7, kDebugParser, "COMMAND_PARSER(ifchar) "); - if (!scumm_stricmp(_char.getName(), _tokens[1])) - _locParseCtxt.script->skip("endif"); + if (!scumm_stricmp(_vm->_char.getName(), _tokens[1])) + _script->skip("endif"); } @@ -316,24 +515,24 @@ DECLARE_COMMAND_PARSER(endif) { DECLARE_COMMAND_PARSER(location) { debugC(7, kDebugParser, "COMMAND_PARSER(location) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._string = strdup(_tokens[1]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._string = strdup(_tokens[1]); + ctxt.nextToken++; - if (_tokens[_locParseCtxt.nextToken][0] != '\0') { - if (isdigit(_tokens[_locParseCtxt.nextToken][0]) || _tokens[_locParseCtxt.nextToken][0] == '-') { - _locParseCtxt.cmd->u._startPos.x = atoi(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._startPos.y = atoi(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + if (_tokens[ctxt.nextToken][0] != '\0') { + if (isdigit(_tokens[ctxt.nextToken][0]) || _tokens[ctxt.nextToken][0] == '-') { + ctxt.cmd->u._startPos.x = atoi(_tokens[ctxt.nextToken]); + ctxt.nextToken++; + ctxt.cmd->u._startPos.y = atoi(_tokens[ctxt.nextToken]); + ctxt.nextToken++; } - if (isdigit(_tokens[_locParseCtxt.nextToken][0]) || _tokens[_locParseCtxt.nextToken][0] == '-') { - _locParseCtxt.cmd->u._startPos2.x = atoi(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._startPos2.y = atoi(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + if (isdigit(_tokens[ctxt.nextToken][0]) || _tokens[ctxt.nextToken][0] == '-') { + ctxt.cmd->u._startPos2.x = atoi(_tokens[ctxt.nextToken]); + ctxt.nextToken++; + ctxt.cmd->u._startPos2.y = atoi(_tokens[ctxt.nextToken]); + ctxt.nextToken++; } } @@ -345,10 +544,10 @@ DECLARE_COMMAND_PARSER(location) { DECLARE_COMMAND_PARSER(string) { debugC(7, kDebugParser, "COMMAND_PARSER(string) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._string = strdup(_tokens[1]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._string = strdup(_tokens[1]); + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -357,12 +556,12 @@ DECLARE_COMMAND_PARSER(string) { DECLARE_COMMAND_PARSER(math) { debugC(7, kDebugParser, "COMMAND_PARSER(math) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._lvalue = _countersNames->lookup(_tokens[1]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._rvalue = atoi(_tokens[2]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._lvalue = _vm->_countersNames->lookup(_tokens[1]); + ctxt.nextToken++; + ctxt.cmd->u._rvalue = atoi(_tokens[2]); + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -372,29 +571,29 @@ DECLARE_COMMAND_PARSER(math) { DECLARE_COMMAND_PARSER(test) { debugC(7, kDebugParser, "COMMAND_PARSER(test) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - uint counter = _countersNames->lookup(_tokens[1]); - _locParseCtxt.nextToken++; + uint counter = _vm->_countersNames->lookup(_tokens[1]); + ctxt.nextToken++; if (counter == Table::notFound) { if (!scumm_stricmp("SFX", _tokens[1])) { - _locParseCtxt.cmd->_id = CMD_TEST_SFX; + ctxt.cmd->_id = CMD_TEST_SFX; } else { error("unknown counter '%s' in test opcode", _tokens[1]); } } else { - _locParseCtxt.cmd->u._lvalue = counter; - _locParseCtxt.cmd->u._rvalue = atoi(_tokens[3]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._lvalue = counter; + ctxt.cmd->u._rvalue = atoi(_tokens[3]); + ctxt.nextToken++; if (_tokens[2][0] == '>') { - _locParseCtxt.cmd->_id = CMD_TEST_GT; + ctxt.cmd->_id = CMD_TEST_GT; } else if (_tokens[2][0] == '<') { - _locParseCtxt.cmd->_id = CMD_TEST_LT; + ctxt.cmd->_id = CMD_TEST_LT; } - _locParseCtxt.nextToken++; + ctxt.nextToken++; } parseCommandFlags(); @@ -405,14 +604,14 @@ DECLARE_COMMAND_PARSER(test) { DECLARE_COMMAND_PARSER(music) { debugC(7, kDebugParser, "COMMAND_PARSER(music) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._musicCommand = _audioCommandsNames->lookup(_tokens[1]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._musicCommand = _audioCommandsNames->lookup(_tokens[1]); + ctxt.nextToken++; if (_tokens[2][0] != '\0' && scumm_stricmp("flags", _tokens[2]) && scumm_stricmp("gflags", _tokens[2])) { - _locParseCtxt.cmd->u._musicParm = atoi(_tokens[2]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._musicParm = atoi(_tokens[2]); + ctxt.nextToken++; } parseCommandFlags(); @@ -423,18 +622,18 @@ DECLARE_COMMAND_PARSER(music) { DECLARE_COMMAND_PARSER(zeta) { debugC(7, kDebugParser, "COMMAND_PARSER(zeta) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._zeta0 = atoi(_tokens[1]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._zeta1 = atoi(_tokens[2]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._zeta0 = atoi(_tokens[1]); + ctxt.nextToken++; + ctxt.cmd->u._zeta1 = atoi(_tokens[2]); + ctxt.nextToken++; if (_tokens[3][0] != '\0') { - _locParseCtxt.cmd->u._zeta2 = atoi(_tokens[3]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._zeta2 = atoi(_tokens[3]); + ctxt.nextToken++; } else { - _locParseCtxt.cmd->u._zeta2 = 50; + ctxt.cmd->u._zeta2 = 50; } parseCommandFlags(); @@ -445,23 +644,23 @@ DECLARE_COMMAND_PARSER(zeta) { DECLARE_COMMAND_PARSER(give) { debugC(7, kDebugParser, "COMMAND_PARSER(give) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._object = 4 + atoi(_tokens[1]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._object = 4 + atoi(_tokens[1]); + ctxt.nextToken++; if (!scumm_stricmp("dino", _tokens[2])) { - _locParseCtxt.cmd->u._characterId = 1; + ctxt.cmd->u._characterId = 1; } else if (!scumm_stricmp("doug", _tokens[2])) { - _locParseCtxt.cmd->u._characterId = 2; + ctxt.cmd->u._characterId = 2; } else if (!scumm_stricmp("donna", _tokens[2])) { - _locParseCtxt.cmd->u._characterId = 3; + ctxt.cmd->u._characterId = 3; } else error("unknown recipient '%s' in give command", _tokens[2]); - _locParseCtxt.nextToken++; + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -471,21 +670,21 @@ DECLARE_COMMAND_PARSER(give) { DECLARE_COMMAND_PARSER(text) { debugC(7, kDebugParser, "COMMAND_PARSER(text) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); if (isdigit(_tokens[1][1])) { - _locParseCtxt.cmd->u._zeta0 = atoi(_tokens[1]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._zeta0 = atoi(_tokens[1]); + ctxt.nextToken++; } else { - _locParseCtxt.cmd->u._zeta0 = -1; + ctxt.cmd->u._zeta0 = -1; } - _locParseCtxt.cmd->u._string = strdup(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._string = strdup(_tokens[ctxt.nextToken]); + ctxt.nextToken++; - if (_tokens[_locParseCtxt.nextToken][0] != '\0' && scumm_stricmp("flags", _tokens[_locParseCtxt.nextToken])) { - _locParseCtxt.cmd->u._string2 = strdup(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + if (_tokens[ctxt.nextToken][0] != '\0' && scumm_stricmp("flags", _tokens[ctxt.nextToken])) { + ctxt.cmd->u._string2 = strdup(_tokens[ctxt.nextToken]); + ctxt.nextToken++; } @@ -497,10 +696,10 @@ DECLARE_COMMAND_PARSER(text) { DECLARE_COMMAND_PARSER(unary) { debugC(7, kDebugParser, "COMMAND_PARSER(unary) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._rvalue = atoi(_tokens[1]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._rvalue = atoi(_tokens[1]); + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -511,14 +710,14 @@ DECLARE_ZONE_PARSER(limits) { debugC(7, kDebugParser, "ZONE_PARSER(limits) "); if (isalpha(_tokens[1][1])) { - _locParseCtxt.z->_flags |= kFlagsAnimLinked; - _locParseCtxt.z->_linkedAnim = findAnimation(_tokens[1]); - _locParseCtxt.z->_linkedName = strdup(_tokens[1]); + ctxt.z->_flags |= kFlagsAnimLinked; + ctxt.z->_linkedAnim = _vm->findAnimation(_tokens[1]); + ctxt.z->_linkedName = strdup(_tokens[1]); } else { - _locParseCtxt.z->_left = atoi(_tokens[1]); - _locParseCtxt.z->_top = atoi(_tokens[2]); - _locParseCtxt.z->_right = atoi(_tokens[3]); - _locParseCtxt.z->_bottom = atoi(_tokens[4]); + ctxt.z->_left = atoi(_tokens[1]); + ctxt.z->_top = atoi(_tokens[2]); + ctxt.z->_right = atoi(_tokens[3]); + ctxt.z->_bottom = atoi(_tokens[4]); } } @@ -526,9 +725,9 @@ DECLARE_ZONE_PARSER(limits) { DECLARE_ZONE_PARSER(moveto) { debugC(7, kDebugParser, "ZONE_PARSER(moveto) "); - _locParseCtxt.z->_moveTo.x = atoi(_tokens[1]); - _locParseCtxt.z->_moveTo.y = atoi(_tokens[2]); -// _locParseCtxt.z->_moveTo.z = atoi(_tokens[3]); + ctxt.z->_moveTo.x = atoi(_tokens[1]); + ctxt.z->_moveTo.y = atoi(_tokens[2]); +// ctxt.z->_moveTo.z = atoi(_tokens[3]); } @@ -536,45 +735,45 @@ DECLARE_ZONE_PARSER(type) { debugC(7, kDebugParser, "ZONE_PARSER(type) "); if (_tokens[2][0] != '\0') { - _locParseCtxt.z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16; + ctxt.z->_type = (4 + _vm->_objectsNames->lookup(_tokens[2])) << 16; } int16 _si = _zoneTypeNames->lookup(_tokens[1]); if (_si != Table::notFound) { - _locParseCtxt.z->_type |= 1 << (_si - 1); - parseZoneTypeBlock(*_locParseCtxt.script, _locParseCtxt.z); + ctxt.z->_type |= 1 << (_si - 1); + parseZoneTypeBlock(ctxt.z); -// if (_locParseCtxt.z->_type & kZoneHear) { +// if (ctxt.z->_type & kZoneHear) { // _soundMan->sfxCommand(START...); // } } - _locationParser->popTables(); + _parser->popTables(); } DECLARE_ANIM_PARSER(file) { debugC(7, kDebugParser, "ANIM_PARSER(file) "); - _locParseCtxt.a->gfxobj = _gfx->loadAnim(_tokens[1]); + ctxt.a->gfxobj = _vm->_gfx->loadAnim(_tokens[1]); } DECLARE_ANIM_PARSER(position) { debugC(7, kDebugParser, "ANIM_PARSER(position) "); - _locParseCtxt.a->_left = atoi(_tokens[1]); - _locParseCtxt.a->_top = atoi(_tokens[2]); - _locParseCtxt.a->_z = atoi(_tokens[3]); - _locParseCtxt.a->_frame = atoi(_tokens[4]); + ctxt.a->_left = atoi(_tokens[1]); + ctxt.a->_top = atoi(_tokens[2]); + ctxt.a->_z = atoi(_tokens[3]); + ctxt.a->_frame = atoi(_tokens[4]); } DECLARE_ANIM_PARSER(moveto) { debugC(7, kDebugParser, "ANIM_PARSER(moveto) "); - _locParseCtxt.a->_moveTo.x = atoi(_tokens[1]); - _locParseCtxt.a->_moveTo.y = atoi(_tokens[2]); -// _locParseCtxt.a->_moveTo.z = atoi(_tokens[3]); + ctxt.a->_moveTo.x = atoi(_tokens[1]); + ctxt.a->_moveTo.y = atoi(_tokens[2]); +// ctxt.a->_moveTo.z = atoi(_tokens[3]); } @@ -582,17 +781,17 @@ DECLARE_ANIM_PARSER(endanimation) { debugC(7, kDebugParser, "ANIM_PARSER(endanimation) "); - if (_locParseCtxt.a->gfxobj) { - _locParseCtxt.a->_right = _locParseCtxt.a->width(); - _locParseCtxt.a->_bottom = _locParseCtxt.a->height(); + if (ctxt.a->gfxobj) { + ctxt.a->_right = ctxt.a->width(); + ctxt.a->_bottom = ctxt.a->height(); } - _locParseCtxt.a->_oldPos.x = -1000; - _locParseCtxt.a->_oldPos.y = -1000; + ctxt.a->_oldPos.x = -1000; + ctxt.a->_oldPos.y = -1000; - _locParseCtxt.a->_flags |= 0x1000000; + ctxt.a->_flags |= 0x1000000; - _locationParser->popTables(); + _parser->popTables(); } @@ -607,7 +806,8 @@ DECLARE_ANIM_PARSER(endanimation) { DECLARE_INSTRUCTION_PARSER(zone) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(zone) "); - _instParseCtxt.inst->_z = findZone(_tokens[1]); + ctxt.inst->_z = _vm->findZone(_tokens[1]); + ctxt.inst->_index = _parser->_lookup; } @@ -616,11 +816,12 @@ DECLARE_INSTRUCTION_PARSER(color) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(color) "); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[1]); - _instParseCtxt.inst->_colors[0] = atoi(_tokens[2]); - _instParseCtxt.inst->_colors[1] = atoi(_tokens[3]); - _instParseCtxt.inst->_colors[2] = atoi(_tokens[4]); + ctxt.inst->_colors[0] = atoi(_tokens[2]); + ctxt.inst->_colors[1] = atoi(_tokens[3]); + ctxt.inst->_colors[2] = atoi(_tokens[4]); + ctxt.inst->_index = _parser->_lookup; } @@ -629,9 +830,10 @@ DECLARE_INSTRUCTION_PARSER(mask) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(mask) "); - parseRValue(_instParseCtxt.inst->_opA, _tokens[1]); - parseRValue(_instParseCtxt.inst->_opB, _tokens[2]); - parseRValue(_instParseCtxt.inst->_opC, _tokens[3]); + parseRValue(ctxt.inst->_opA, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[2]); + parseRValue(ctxt.inst->_opC, _tokens[3]); + ctxt.inst->_index = _parser->_lookup; } @@ -639,7 +841,8 @@ DECLARE_INSTRUCTION_PARSER(mask) { DECLARE_INSTRUCTION_PARSER(print) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(print) "); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[1]); + ctxt.inst->_index = _parser->_lookup; } @@ -650,18 +853,19 @@ DECLARE_INSTRUCTION_PARSER(text) { int _si = 1; if (isdigit(_tokens[1][1])) { - _instParseCtxt.inst->_y = atoi(_tokens[1]); + ctxt.inst->_y = atoi(_tokens[1]); _si = 2; } else { - _instParseCtxt.inst->_y = -1; + ctxt.inst->_y = -1; } - _instParseCtxt.inst->_text = strdup(_tokens[_si]); + ctxt.inst->_text = strdup(_tokens[_si]); _si++; if (_tokens[_si][0] != '\0' && scumm_stricmp("flags", _tokens[_si])) { - _instParseCtxt.inst->_text2 = strdup(_tokens[_si]); + ctxt.inst->_text2 = strdup(_tokens[_si]); } + ctxt.inst->_index = _parser->_lookup; } @@ -670,24 +874,24 @@ DECLARE_INSTRUCTION_PARSER(if_op) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(if_op) "); - if (_instParseCtxt.openIf) + if (ctxt.openIf) error("cannot nest 'if' blocks"); - parseLValue(_instParseCtxt.inst->_opA, _tokens[1]); - parseRValue(_instParseCtxt.inst->_opB, _tokens[3]); + parseLValue(ctxt.inst->_opA, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[3]); if (_tokens[2][0] == '=') { - _instParseCtxt.inst->_index = INST_IFEQ; + ctxt.inst->_index = INST_IFEQ; } else if (_tokens[2][0] == '>') { - _instParseCtxt.inst->_index = INST_IFGT; + ctxt.inst->_index = INST_IFGT; } else if (_tokens[2][0] == '<') { - _instParseCtxt.inst->_index = INST_IFLT; + ctxt.inst->_index = INST_IFLT; } else error("unknown test operator '%s' in if-clause", _tokens[2]); - _instParseCtxt.openIf = _instParseCtxt.inst; + ctxt.openIf = ctxt.inst; } @@ -695,35 +899,36 @@ DECLARE_INSTRUCTION_PARSER(if_op) { DECLARE_INSTRUCTION_PARSER(endif) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(endif) "); - if (!_instParseCtxt.openIf) + if (!ctxt.openIf) error("unexpected 'endif'"); -// _instParseCtxt.openIf->_endif = _instParseCtxt.inst; - _instParseCtxt.openIf = nullInstructionPtr; +// ctxt.openIf->_endif = ctxt.inst; + ctxt.openIf = nullInstructionPtr; + ctxt.inst->_index = _parser->_lookup; } -void Parallaction_br::parseRValue(ScriptVar &v, const char *str) { +void ProgramParser_br::parseRValue(ScriptVar &v, const char *str) { if (isdigit(str[0]) || str[0] == '-') { v.setImmediate(atoi(str)); return; } - int index = _instParseCtxt.program->findLocal(str); + int index = _program->findLocal(str); if (index != -1) { - v.setLocal(&_instParseCtxt.locals[index]); + v.setLocal(&ctxt.locals[index]); return; } AnimationPtr a; if (str[1] == '.') { - a = findAnimation(&str[2]); + a = _vm->findAnimation(&str[2]); if (!a) { error("unknown animation '%s' in script", &str[2]); } } else - a = AnimationPtr(_instParseCtxt.a); + a = AnimationPtr(ctxt.a); if (str[0] == 'X') { v.setField(&a->_left); @@ -744,197 +949,186 @@ void Parallaction_br::parseRValue(ScriptVar &v, const char *str) { v.setRandom(atoi(&str[1])); } else if (str[0] == 'L') { - v.setField(&_lipSyncVal); + v.setField(&_vm->_lipSyncVal); } } -typedef OpcodeImpl<Parallaction_br> OpcodeV2; -#define INSTRUCTION_PARSER(sig) OpcodeV2(this, &Parallaction_br::instParse_##sig) -#define ZONE_PARSER(sig) OpcodeV2(this, &Parallaction_br::locZoneParse_##sig) -#define ANIM_PARSER(sig) OpcodeV2(this, &Parallaction_br::locAnimParse_##sig) -#define LOCATION_PARSER(sig) OpcodeV2(this, &Parallaction_br::locParse_##sig) -#define COMMAND_PARSER(sig) OpcodeV2(this, &Parallaction_br::cmdParse_##sig) - -#define WARNING_PARSER(sig) OpcodeV2(this, &Parallaction_br::warning_##sig) - -void Parallaction_br::initParsers() { - - _locationParser = new Parser; - - static const OpcodeV2 op0[] = { - INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition - INSTRUCTION_PARSER(zone), // on - INSTRUCTION_PARSER(zone), // off - INSTRUCTION_PARSER(x), - INSTRUCTION_PARSER(y), - INSTRUCTION_PARSER(z), - INSTRUCTION_PARSER(f), - INSTRUCTION_PARSER(loop), - INSTRUCTION_PARSER(null), // endloop - INSTRUCTION_PARSER(null), // show - INSTRUCTION_PARSER(inc), - INSTRUCTION_PARSER(inc), // dec - INSTRUCTION_PARSER(set), - INSTRUCTION_PARSER(put), - INSTRUCTION_PARSER(call), - INSTRUCTION_PARSER(null), // wait - INSTRUCTION_PARSER(zone), // start - INSTRUCTION_PARSER(zone), // process - INSTRUCTION_PARSER(move), - INSTRUCTION_PARSER(color), - INSTRUCTION_PARSER(zone), // sound - INSTRUCTION_PARSER(mask), - INSTRUCTION_PARSER(print), - INSTRUCTION_PARSER(text), - INSTRUCTION_PARSER(inc), // mul - INSTRUCTION_PARSER(inc), // div - INSTRUCTION_PARSER(if_op), - INSTRUCTION_PARSER(null), - INSTRUCTION_PARSER(null), - INSTRUCTION_PARSER(endif), - INSTRUCTION_PARSER(zone), // stop - INSTRUCTION_PARSER(endscript) - }; - - uint i; - for (i = 0; i < ARRAYSIZE(op0); i++) - _instructionParsers.push_back(&op0[i]); - - - static const OpcodeV2 op2[] = { - WARNING_PARSER(unexpected), - COMMAND_PARSER(flags), // set - COMMAND_PARSER(flags), // clear - COMMAND_PARSER(zone), // start - COMMAND_PARSER(zone), // speak - COMMAND_PARSER(zone), // get - COMMAND_PARSER(location), - COMMAND_PARSER(zone), // open - COMMAND_PARSER(zone), // close - COMMAND_PARSER(zone), // on - COMMAND_PARSER(zone), // off - COMMAND_PARSER(call), - COMMAND_PARSER(flags), // toggle - COMMAND_PARSER(drop), - COMMAND_PARSER(simple), // quit - COMMAND_PARSER(move), - COMMAND_PARSER(zone), // stop - COMMAND_PARSER(string), // character - COMMAND_PARSER(string), // followme - COMMAND_PARSER(simple), // onmouse - COMMAND_PARSER(simple), // offmouse - COMMAND_PARSER(drop), // add - COMMAND_PARSER(zone), // leave - COMMAND_PARSER(math), // inc - COMMAND_PARSER(math), // dec - COMMAND_PARSER(test), // test - WARNING_PARSER(unexpected), - WARNING_PARSER(unexpected), - COMMAND_PARSER(math), // let - COMMAND_PARSER(music), - COMMAND_PARSER(zone), // fix - COMMAND_PARSER(zone), // unfix - COMMAND_PARSER(zeta), - COMMAND_PARSER(unary), // scroll - COMMAND_PARSER(string), // swap - COMMAND_PARSER(give), - COMMAND_PARSER(text), - COMMAND_PARSER(unary), // part - WARNING_PARSER(unexpected), - COMMAND_PARSER(simple), // return - COMMAND_PARSER(simple), // onsave - COMMAND_PARSER(simple), // offsave - COMMAND_PARSER(endcommands), // endcommands - COMMAND_PARSER(ifchar), - COMMAND_PARSER(endif) - }; - - for (i = 0; i < ARRAYSIZE(op2); i++) - _commandParsers.push_back(&op2[i]); - - static const OpcodeV2 op4[] = { - WARNING_PARSER(unexpected), - LOCATION_PARSER(character), - LOCATION_PARSER(endlocation), - LOCATION_PARSER(ifchar), - LOCATION_PARSER(null), // endif - LOCATION_PARSER(location), - LOCATION_PARSER(mask), - LOCATION_PARSER(path), - LOCATION_PARSER(null), // disk - LOCATION_PARSER(localflags), - LOCATION_PARSER(commands), - LOCATION_PARSER(escape), - LOCATION_PARSER(acommands), - LOCATION_PARSER(flags), - LOCATION_PARSER(comment), - LOCATION_PARSER(endcomment), - LOCATION_PARSER(zone), - LOCATION_PARSER(animation), - LOCATION_PARSER(zeta), - LOCATION_PARSER(music), - LOCATION_PARSER(sound) - }; - - for (i = 0; i < ARRAYSIZE(op4); i++) - _locationParsers.push_back(&op4[i]); - - static const OpcodeV2 op5[] = { - WARNING_PARSER(unexpected), - ZONE_PARSER(endzone), - ZONE_PARSER(limits), - ZONE_PARSER(moveto), - ZONE_PARSER(type), - ZONE_PARSER(commands), - ZONE_PARSER(label), - ZONE_PARSER(flags) - }; - - for (i = 0; i < ARRAYSIZE(op5); i++) - _locationZoneParsers.push_back(&op5[i]); - - static const OpcodeV2 op6[] = { - WARNING_PARSER(unexpected), - ANIM_PARSER(endanimation), - ANIM_PARSER(endanimation), // endzone - ANIM_PARSER(script), - ANIM_PARSER(commands), - ANIM_PARSER(type), - ANIM_PARSER(label), - ANIM_PARSER(flags), - ANIM_PARSER(file), - ANIM_PARSER(position), - ANIM_PARSER(moveto) - }; - - for (i = 0; i < ARRAYSIZE(op6); i++) - _locationAnimParsers.push_back(&op6[i]); -} - -void Parallaction_br::parseLocation(const char* filename) { - - _locParseCtxt.numZones = 0; - _locParseCtxt.bgName = 0; - _locParseCtxt.maskName = 0; - _locParseCtxt.pathName = 0; - - Super::parseLocation(filename); - - _gfx->setBackground(kBackgroundLocation, _locParseCtxt.bgName, _locParseCtxt.maskName, _locParseCtxt.pathName); - _pathBuffer = &_gfx->_backgroundInfo.path; - - free(_locParseCtxt.bgName); - free(_locParseCtxt.maskName); - free(_locParseCtxt.pathName); - -// drawZones(); - - return; + +void LocationParser_br::init() { + + _parser = new Parser; + + _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_br), _zoneFlagNamesRes_br); + _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_br), _zoneTypeNamesRes_br); + _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_br), _commandsNamesRes_br); + _audioCommandsNames = new Table(ARRAYSIZE(_audioCommandsNamesRes_br), _audioCommandsNamesRes_br); + _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_br), _locationStmtRes_br); + _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_br), _locationZoneStmtRes_br); + _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_br), _locationAnimStmtRes_br); + + Common::Array<const Opcode*> *table = 0; + + SetOpcodeTable(_commandParsers); + WARNING_PARSER(unexpected); + COMMAND_PARSER(flags); // set + COMMAND_PARSER(flags); // clear + COMMAND_PARSER(zone); // start + COMMAND_PARSER(zone); // speak + COMMAND_PARSER(zone); // get + COMMAND_PARSER(location); + COMMAND_PARSER(zone); // open + COMMAND_PARSER(zone); // close + COMMAND_PARSER(zone); // on + COMMAND_PARSER(zone); // off + COMMAND_PARSER(call); + COMMAND_PARSER(flags); // toggle + COMMAND_PARSER(drop); + COMMAND_PARSER(simple); // quit + COMMAND_PARSER(move); + COMMAND_PARSER(zone); // stop + COMMAND_PARSER(string); // character + COMMAND_PARSER(string); // followme + COMMAND_PARSER(simple); // onmouse + COMMAND_PARSER(simple); // offmouse + COMMAND_PARSER(drop); // add + COMMAND_PARSER(zone); // leave + COMMAND_PARSER(math); // inc + COMMAND_PARSER(math); // dec + COMMAND_PARSER(test); // test + WARNING_PARSER(unexpected); + WARNING_PARSER(unexpected); + COMMAND_PARSER(math); // let + COMMAND_PARSER(music); + COMMAND_PARSER(zone); // fix + COMMAND_PARSER(zone); // unfix + COMMAND_PARSER(zeta); + COMMAND_PARSER(unary); // scroll + COMMAND_PARSER(string); // swap + COMMAND_PARSER(give); + COMMAND_PARSER(text); + COMMAND_PARSER(unary); // part + WARNING_PARSER(unexpected); + COMMAND_PARSER(simple); // return + COMMAND_PARSER(simple); // onsave + COMMAND_PARSER(simple); // offsave + COMMAND_PARSER(endcommands); // endcommands + COMMAND_PARSER(ifchar); + COMMAND_PARSER(endif); + + SetOpcodeTable(_locationParsers); + WARNING_PARSER(unexpected); + LOCATION_PARSER(character); + LOCATION_PARSER(endlocation); + LOCATION_PARSER(ifchar); + LOCATION_PARSER(null); // endif + LOCATION_PARSER(location); + LOCATION_PARSER(mask); + LOCATION_PARSER(path); + LOCATION_PARSER(null); // disk + LOCATION_PARSER(localflags); + LOCATION_PARSER(commands); + LOCATION_PARSER(escape); + LOCATION_PARSER(acommands); + LOCATION_PARSER(flags); + LOCATION_PARSER(comment); + LOCATION_PARSER(endcomment); + LOCATION_PARSER(zone); + LOCATION_PARSER(animation); + LOCATION_PARSER(zeta); + LOCATION_PARSER(music); + LOCATION_PARSER(sound); + + SetOpcodeTable(_locationZoneParsers); + WARNING_PARSER(unexpected); + ZONE_PARSER(endzone); + ZONE_PARSER(limits); + ZONE_PARSER(moveto); + ZONE_PARSER(type); + ZONE_PARSER(commands); + ZONE_PARSER(label); + ZONE_PARSER(flags); + + + SetOpcodeTable(_locationAnimParsers); + WARNING_PARSER(unexpected); + ANIM_PARSER(endanimation); + ANIM_PARSER(endanimation); // endzone + ANIM_PARSER(script); + ANIM_PARSER(commands); + ANIM_PARSER(type); + ANIM_PARSER(label); + ANIM_PARSER(flags); + ANIM_PARSER(file); + ANIM_PARSER(position); + ANIM_PARSER(moveto); +} + +void ProgramParser_br::init() { + + _parser = new Parser; + + _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes_br), _instructionNamesRes_br); + + Common::Array<const Opcode*> *table = 0; + + SetOpcodeTable(_instructionParsers); + INSTRUCTION_PARSER(defLocal); // invalid opcode -> local definition + INSTRUCTION_PARSER(zone); // on + INSTRUCTION_PARSER(zone); // off + INSTRUCTION_PARSER(x); + INSTRUCTION_PARSER(y); + INSTRUCTION_PARSER(z); + INSTRUCTION_PARSER(f); + INSTRUCTION_PARSER(loop); + INSTRUCTION_PARSER(null); // endloop + INSTRUCTION_PARSER(null); // show + INSTRUCTION_PARSER(inc); + INSTRUCTION_PARSER(inc); // dec + INSTRUCTION_PARSER(set); + INSTRUCTION_PARSER(put); + INSTRUCTION_PARSER(call); + INSTRUCTION_PARSER(null); // wait + INSTRUCTION_PARSER(zone); // start + INSTRUCTION_PARSER(zone); // process + INSTRUCTION_PARSER(move); + INSTRUCTION_PARSER(color); + INSTRUCTION_PARSER(zone); // sound + INSTRUCTION_PARSER(mask); + INSTRUCTION_PARSER(print); + INSTRUCTION_PARSER(text); + INSTRUCTION_PARSER(inc); // mul + INSTRUCTION_PARSER(inc); // div + INSTRUCTION_PARSER(if_op); + INSTRUCTION_PARSER(null); + INSTRUCTION_PARSER(null); + INSTRUCTION_PARSER(endif); + INSTRUCTION_PARSER(zone); // stop + INSTRUCTION_PARSER(endscript); } +void LocationParser_br::parse(Script *script) { + + ctxt.numZones = 0; + ctxt.bgName = 0; + ctxt.maskName = 0; + ctxt.pathName = 0; + ctxt.characterName = 0; + LocationParser_ns::parse(script); + _vm->_gfx->setBackground(kBackgroundLocation, ctxt.bgName, ctxt.maskName, ctxt.pathName); + _vm->_pathBuffer = &_vm->_gfx->_backgroundInfo.path; + if (ctxt.characterName) { + _vm->changeCharacter(ctxt.characterName); + } + + free(ctxt.bgName); + free(ctxt.maskName); + free(ctxt.pathName); + free(ctxt.characterName); + +} } // namespace Parallaction diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp index b8b36a0885..2c4601c938 100644 --- a/engines/parallaction/parser_ns.cpp +++ b/engines/parallaction/parser_ns.cpp @@ -67,29 +67,143 @@ namespace Parallaction { #define INST_END 19 -#define DECLARE_ZONE_PARSER(sig) void Parallaction_ns::locZoneParse_##sig() -#define DECLARE_ANIM_PARSER(sig) void Parallaction_ns::locAnimParse_##sig() -#define DECLARE_COMMAND_PARSER(sig) void Parallaction_ns::cmdParse_##sig() -#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction_ns::instParse_##sig() -#define DECLARE_LOCATION_PARSER(sig) void Parallaction_ns::locParse_##sig() - - -void Parallaction_ns::warning_unexpected() { - debugC(1, kDebugParser, "unexpected keyword '%s' in line %i", _tokens[0], _locParseCtxt.script->getLine()); +const char *_zoneFlagNamesRes_ns[] = { + "closed", + "active", + "remove", + "acting", + "locked", + "fixed", + "noname", + "nomasked", + "looping", + "added", + "character", + "nowalk" +}; + +const char *_zoneTypeNamesRes_ns[] = { + "examine", + "door", + "get", + "merge", + "taste", + "hear", + "feel", + "speak", + "none", + "trap", + "yourself", + "Command" +}; + +const char *_commandsNamesRes_ns[] = { + "set", + "clear", + "start", + "speak", + "get", + "location", + "open", + "close", + "on", + "off", + "call", + "toggle", + "drop", + "quit", + "move", + "stop", + "endcommands", + "endzone" +}; + +const char *_locationStmtRes_ns[] = { + "endlocation", + "location", + "disk", + "nodes", + "zone", + "animation", + "localflags", + "commands", + "acommands", + "flags", + "comment", + "endcomment", + "sound", + "music" +}; + +const char *_locationZoneStmtRes_ns[] = { + "limits", + "moveto", + "type", + "commands", + "label", + "flags", + "endzone" +}; + +const char *_locationAnimStmtRes_ns[] = { + "script", + "commands", + "type", + "label", + "flags", + "file", + "position", + "moveto", + "endanimation" +}; + +const char *_instructionNamesRes_ns[] = { + "on", + "off", + "x", + "y", + "z", + "f", + "loop", + "endloop", + "show", + "inc", + "dec", + "set", + "put", + "call", + "wait", + "start", + "sound", + "move", + "endscript" +}; + + +#define DECLARE_ZONE_PARSER(sig) void LocationParser_ns::locZoneParse_##sig() +#define DECLARE_ANIM_PARSER(sig) void LocationParser_ns::locAnimParse_##sig() +#define DECLARE_COMMAND_PARSER(sig) void LocationParser_ns::cmdParse_##sig() +#define DECLARE_LOCATION_PARSER(sig) void LocationParser_ns::locParse_##sig() + +#define DECLARE_INSTRUCTION_PARSER(sig) void ProgramParser_ns::instParse_##sig() + + +void LocationParser_ns::warning_unexpected() { + debugC(1, kDebugParser, "unexpected keyword '%s' in line %i", _tokens[0], _script->getLine()); } DECLARE_ANIM_PARSER(script) { debugC(7, kDebugParser, "ANIM_PARSER(script) "); - _locParseCtxt.a->_scriptName = strdup(_tokens[1]); + ctxt.a->_scriptName = strdup(_tokens[1]); } DECLARE_ANIM_PARSER(commands) { debugC(7, kDebugParser, "ANIM_PARSER(commands) "); - parseCommands(*_locParseCtxt.script, _locParseCtxt.a->_commands); + parseCommands(ctxt.a->_commands); } @@ -97,29 +211,29 @@ DECLARE_ANIM_PARSER(type) { debugC(7, kDebugParser, "ANIM_PARSER(type) "); if (_tokens[2][0] != '\0') { - _locParseCtxt.a->_type = ((4 + _objectsNames->lookup(_tokens[2])) << 16) & 0xFFFF0000; + ctxt.a->_type = ((4 + _vm->_objectsNames->lookup(_tokens[2])) << 16) & 0xFFFF0000; } int16 _si = _zoneTypeNames->lookup(_tokens[1]); if (_si != Table::notFound) { - _locParseCtxt.a->_type |= 1 << (_si-1); - if (((_locParseCtxt.a->_type & 0xFFFF) != kZoneNone) && ((_locParseCtxt.a->_type & 0xFFFF) != kZoneCommand)) { - parseZoneTypeBlock(*_locParseCtxt.script, _locParseCtxt.a); + ctxt.a->_type |= 1 << (_si-1); + if (((ctxt.a->_type & 0xFFFF) != kZoneNone) && ((ctxt.a->_type & 0xFFFF) != kZoneCommand)) { + parseZoneTypeBlock(ctxt.a); } } - _locParseCtxt.a->_oldPos.x = -1000; - _locParseCtxt.a->_oldPos.y = -1000; + ctxt.a->_oldPos.x = -1000; + ctxt.a->_oldPos.y = -1000; - _locParseCtxt.a->_flags |= 0x1000000; + ctxt.a->_flags |= 0x1000000; - _locationParser->popTables(); + _parser->popTables(); } DECLARE_ANIM_PARSER(label) { debugC(7, kDebugParser, "ANIM_PARSER(label) "); - _locParseCtxt.a->_label = _gfx->renderFloatingLabel(_labelFont, _tokens[1]); + ctxt.a->_label = _vm->_gfx->renderFloatingLabel(_vm->_labelFont, _tokens[1]); } @@ -131,7 +245,7 @@ DECLARE_ANIM_PARSER(flags) { do { byte _al = _zoneFlagNames->lookup(_tokens[_si]); _si++; - _locParseCtxt.a->_flags |= 1 << (_al - 1); + ctxt.a->_flags |= 1 << (_al - 1); } while (!scumm_stricmp(_tokens[_si++], "|")); } @@ -146,24 +260,24 @@ DECLARE_ANIM_PARSER(file) { strcat(vC8, "tras"); } } - _locParseCtxt.a->gfxobj = _gfx->loadAnim(vC8); + ctxt.a->gfxobj = _vm->_gfx->loadAnim(vC8); } DECLARE_ANIM_PARSER(position) { debugC(7, kDebugParser, "ANIM_PARSER(position) "); - _locParseCtxt.a->_left = atoi(_tokens[1]); - _locParseCtxt.a->_top = atoi(_tokens[2]); - _locParseCtxt.a->_z = atoi(_tokens[3]); + ctxt.a->_left = atoi(_tokens[1]); + ctxt.a->_top = atoi(_tokens[2]); + ctxt.a->_z = atoi(_tokens[3]); } DECLARE_ANIM_PARSER(moveto) { debugC(7, kDebugParser, "ANIM_PARSER(moveto) "); - _locParseCtxt.a->_moveTo.x = atoi(_tokens[1]); - _locParseCtxt.a->_moveTo.y = atoi(_tokens[2]); + ctxt.a->_moveTo.x = atoi(_tokens[1]); + ctxt.a->_moveTo.y = atoi(_tokens[2]); } @@ -171,15 +285,15 @@ DECLARE_ANIM_PARSER(endanimation) { debugC(7, kDebugParser, "ANIM_PARSER(endanimation) "); - _locParseCtxt.a->_oldPos.x = -1000; - _locParseCtxt.a->_oldPos.y = -1000; + ctxt.a->_oldPos.x = -1000; + ctxt.a->_oldPos.y = -1000; - _locParseCtxt.a->_flags |= 0x1000000; + ctxt.a->_flags |= 0x1000000; - _locationParser->popTables(); + _parser->popTables(); } -void Parallaction_ns::parseAnimation(Script& script, AnimationList &list, char *name) { +void LocationParser_ns::parseAnimation(AnimationList &list, char *name) { debugC(5, kDebugParser, "parseAnimation(name: %s)", name); AnimationPtr a(new Animation); @@ -188,37 +302,55 @@ void Parallaction_ns::parseAnimation(Script& script, AnimationList &list, char * list.push_front(AnimationPtr(a)); - _locParseCtxt.a = a; - _locParseCtxt.script = &script; - - _locationParser->pushTables(&_locationAnimParsers, _locationAnimStmt); + ctxt.a = a; + _parser->pushTables(&_locationAnimParsers, _locationAnimStmt); } -void Parallaction_ns::parseInstruction(ProgramPtr program) { +void ProgramParser_ns::parseInstruction() { - InstructionPtr inst(new Instruction); + _script->readLineToken(true); if (_tokens[0][1] == '.') { _tokens[0][1] = '\0'; - _instParseCtxt.a = findAnimation(&_tokens[0][2]); + ctxt.a = _vm->findAnimation(&_tokens[0][2]); } else if (_tokens[1][1] == '.') { _tokens[1][1] = '\0'; - _instParseCtxt.a = findAnimation(&_tokens[1][2]); + ctxt.a = _vm->findAnimation(&_tokens[1][2]); } else - _instParseCtxt.a = program->_anim; - - inst->_index = _instructionNames->lookup(_tokens[0]); - _instParseCtxt.inst = inst; - _instParseCtxt.locals = program->_locals; + ctxt.a = _program->_anim; - (*(_instructionParsers[inst->_index]))(); + if (!ctxt.a) { + return; + } - program->_instructions.push_back(inst); + InstructionPtr inst(new Instruction); + ctxt.inst = inst; + _parser->parseStatement(); + _program->_instructions.push_back(inst); return; } +void ProgramParser_ns::parse(Script *script, ProgramPtr program) { + + _script = script; + _program = program; + + ctxt.openIf = nullInstructionPtr; + ctxt.end = false; + ctxt.locals = program->_locals; + + _parser->reset(); + _parser->pushTables(&_instructionParsers, _instructionNames); + do { + parseInstruction(); + } while (!ctxt.end); + _parser->popTables(); + + program->_ip = program->_instructions.begin(); +} + void Parallaction_ns::loadProgram(AnimationPtr a, const char *filename) { debugC(1, kDebugParser, "loadProgram(Animation: %s, script: %s)", a->_name, filename); @@ -226,20 +358,11 @@ void Parallaction_ns::loadProgram(AnimationPtr a, const char *filename) { ProgramPtr program(new Program); program->_anim = a; - _instParseCtxt.openIf = nullInstructionPtr; - _instParseCtxt.end = false; - _instParseCtxt.program = program; - - do { - script->readLineToken(); - parseInstruction(program); - } while (!_instParseCtxt.end); - - program->_ip = program->_instructions.begin(); + _programParser->parse(script, program); delete script; - _location._programs.push_back(program); + _vm->_location._programs.push_back(program); debugC(1, kDebugParser, "loadProgram() done"); @@ -249,62 +372,70 @@ void Parallaction_ns::loadProgram(AnimationPtr a, const char *filename) { DECLARE_INSTRUCTION_PARSER(animation) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(animation) "); - if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_name)) { - _instParseCtxt.inst->_a = _instParseCtxt.a; + if (!scumm_stricmp(_tokens[1], ctxt.a->_name)) { + ctxt.inst->_a = ctxt.a; } else { - _instParseCtxt.inst->_a = findAnimation(_tokens[1]); + ctxt.inst->_a = _vm->findAnimation(_tokens[1]); } + + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(loop) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(loop) "); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[1]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(x) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(x) "); - parseLValue(_instParseCtxt.inst->_opA, "X"); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseLValue(ctxt.inst->_opA, "X"); + parseRValue(ctxt.inst->_opB, _tokens[1]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(y) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(y) "); - parseLValue(_instParseCtxt.inst->_opA, "Y"); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseLValue(ctxt.inst->_opA, "Y"); + parseRValue(ctxt.inst->_opB, _tokens[1]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(z) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(z) "); - parseLValue(_instParseCtxt.inst->_opA, "Z"); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseLValue(ctxt.inst->_opA, "Z"); + parseRValue(ctxt.inst->_opB, _tokens[1]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(f) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(f) "); - parseLValue(_instParseCtxt.inst->_opA, "F"); - parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + parseLValue(ctxt.inst->_opA, "F"); + parseRValue(ctxt.inst->_opB, _tokens[1]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(inc) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(inc) "); - parseLValue(_instParseCtxt.inst->_opA, _tokens[1]); - parseRValue(_instParseCtxt.inst->_opB, _tokens[2]); + parseLValue(ctxt.inst->_opA, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[2]); if (!scumm_stricmp(_tokens[3], "mod")) { - _instParseCtxt.inst->_flags |= kInstMod; + ctxt.inst->_flags |= kInstMod; } + ctxt.inst->_index = _parser->_lookup; } @@ -316,61 +447,65 @@ DECLARE_INSTRUCTION_PARSER(set) { // script was commented out on Dos version. This workaround enables the engine // to dynamically add a local variable when it is encountered the first time in // the script, so should fix any other occurrence as well. - if (_instParseCtxt.program->findLocal(_tokens[1]) == -1) { - _instParseCtxt.program->addLocal(_tokens[1]); + if (_program->findLocal(_tokens[1]) == -1) { + _program->addLocal(_tokens[1]); } - parseLValue(_instParseCtxt.inst->_opA, _tokens[1]); - parseRValue(_instParseCtxt.inst->_opB, _tokens[2]); + parseLValue(ctxt.inst->_opA, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[2]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(move) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(move) "); - parseRValue(_instParseCtxt.inst->_opA, _tokens[1]); - parseRValue(_instParseCtxt.inst->_opB, _tokens[2]); + parseRValue(ctxt.inst->_opA, _tokens[1]); + parseRValue(ctxt.inst->_opB, _tokens[2]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(put) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(put) "); - if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_name)) { - _instParseCtxt.inst->_a = _instParseCtxt.a; + if (!scumm_stricmp(_tokens[1], ctxt.a->_name)) { + ctxt.inst->_a = ctxt.a; } else { - _instParseCtxt.inst->_a = findAnimation(_tokens[1]); + ctxt.inst->_a = _vm->findAnimation(_tokens[1]); } - parseRValue(_instParseCtxt.inst->_opA, _tokens[2]); - parseRValue(_instParseCtxt.inst->_opB, _tokens[3]); + parseRValue(ctxt.inst->_opA, _tokens[2]); + parseRValue(ctxt.inst->_opB, _tokens[3]); if (!scumm_stricmp(_tokens[4], "masked")) { - _instParseCtxt.inst->_flags |= kInstMaskedPut; + ctxt.inst->_flags |= kInstMaskedPut; } + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(call) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(call) "); - int index = _callableNames->lookup(_tokens[1]); + int index = _vm->_callableNames->lookup(_tokens[1]); if (index == Table::notFound) error("unknown callable '%s'", _tokens[1]); - _instParseCtxt.inst->_immediate = index - 1; + ctxt.inst->_immediate = index - 1; + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(sound) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(sound) "); - _instParseCtxt.inst->_z = findZone(_tokens[1]); + ctxt.inst->_z = _vm->findZone(_tokens[1]); + ctxt.inst->_index = _parser->_lookup; } DECLARE_INSTRUCTION_PARSER(null) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(null) "); - - + ctxt.inst->_index = _parser->_lookup; } @@ -381,43 +516,44 @@ DECLARE_INSTRUCTION_PARSER(defLocal) { int16 index; if (_tokens[3][0] != '\0') { - index = _instParseCtxt.program->addLocal(_tokens[0], val, atoi(_tokens[3]), atoi(_tokens[4])); + index = _program->addLocal(_tokens[0], val, atoi(_tokens[3]), atoi(_tokens[4])); } else { - index = _instParseCtxt.program->addLocal(_tokens[0], val); + index = _program->addLocal(_tokens[0], val); } - _instParseCtxt.inst->_opA.setLocal(&_instParseCtxt.locals[index]); - _instParseCtxt.inst->_opB.setImmediate(_instParseCtxt.locals[index]._value); + ctxt.inst->_opA.setLocal(&ctxt.locals[index]); + ctxt.inst->_opB.setImmediate(ctxt.locals[index]._value); - _instParseCtxt.inst->_index = INST_SET; + ctxt.inst->_index = INST_SET; } DECLARE_INSTRUCTION_PARSER(endscript) { debugC(7, kDebugParser, "INSTRUCTION_PARSER(endscript) "); - _instParseCtxt.end = true; + ctxt.end = true; + ctxt.inst->_index = _parser->_lookup; } -void Parallaction_ns::parseRValue(ScriptVar &v, const char *str) { +void ProgramParser_ns::parseRValue(ScriptVar &v, const char *str) { if (isdigit(str[0]) || str[0] == '-') { v.setImmediate(atoi(str)); return; } - int index = _instParseCtxt.program->findLocal(str); + int index = _program->findLocal(str); if (index != -1) { - v.setLocal(&_instParseCtxt.locals[index]); + v.setLocal(&ctxt.locals[index]); return; } AnimationPtr a; if (str[1] == '.') { - a = findAnimation(&str[2]); + a = _vm->findAnimation(&str[2]); } else { - a = _instParseCtxt.a; + a = ctxt.a; } if (str[0] == 'X') { @@ -435,19 +571,19 @@ void Parallaction_ns::parseRValue(ScriptVar &v, const char *str) { } -void Parallaction_ns::parseLValue(ScriptVar &v, const char *str) { +void ProgramParser_ns::parseLValue(ScriptVar &v, const char *str) { - int index = _instParseCtxt.program->findLocal(str); + int index = _program->findLocal(str); if (index != -1) { - v.setLocal(&_instParseCtxt.locals[index]); + v.setLocal(&ctxt.locals[index]); return; } AnimationPtr a; if (str[1] == '.') { - a = findAnimation(&str[2]); + a = _vm->findAnimation(&str[2]); } else { - a = _instParseCtxt.a; + a = ctxt.a; } if (str[0] == 'X') { @@ -469,23 +605,23 @@ void Parallaction_ns::parseLValue(ScriptVar &v, const char *str) { DECLARE_COMMAND_PARSER(flags) { debugC(7, kDebugParser, "COMMAND_PARSER(flags) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - if (_globalTable->lookup(_tokens[1]) == Table::notFound) { + if (_vm->_globalTable->lookup(_tokens[1]) == Table::notFound) { do { - char _al = _localFlagNames->lookup(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._flags |= 1 << (_al - 1); - } while (!scumm_stricmp(_tokens[_locParseCtxt.nextToken++], "|")); - _locParseCtxt.nextToken--; + char _al = _vm->_localFlagNames->lookup(_tokens[ctxt.nextToken]); + ctxt.nextToken++; + ctxt.cmd->u._flags |= 1 << (_al - 1); + } while (!scumm_stricmp(_tokens[ctxt.nextToken++], "|")); + ctxt.nextToken--; } else { - _locParseCtxt.cmd->u._flags |= kFlagsGlobal; + ctxt.cmd->u._flags |= kFlagsGlobal; do { - char _al = _globalTable->lookup(_tokens[1]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._flags |= 1 << (_al - 1); - } while (!scumm_stricmp(_tokens[_locParseCtxt.nextToken++], "|")); - _locParseCtxt.nextToken--; + char _al = _vm->_globalTable->lookup(_tokens[1]); + ctxt.nextToken++; + ctxt.cmd->u._flags |= 1 << (_al - 1); + } while (!scumm_stricmp(_tokens[ctxt.nextToken++], "|")); + ctxt.nextToken--; } parseCommandFlags(); @@ -496,13 +632,13 @@ DECLARE_COMMAND_PARSER(flags) { DECLARE_COMMAND_PARSER(zone) { debugC(7, kDebugParser, "COMMAND_PARSER(zone) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._zone = findZone(_tokens[_locParseCtxt.nextToken]); - if (!_locParseCtxt.cmd->u._zone) { - saveCommandForward(_tokens[_locParseCtxt.nextToken], _locParseCtxt.cmd); + ctxt.cmd->u._zone = _vm->findZone(_tokens[ctxt.nextToken]); + if (!ctxt.cmd->u._zone) { + saveCommandForward(_tokens[ctxt.nextToken], ctxt.cmd); } - _locParseCtxt.nextToken++; + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -512,10 +648,10 @@ DECLARE_COMMAND_PARSER(zone) { DECLARE_COMMAND_PARSER(location) { debugC(7, kDebugParser, "COMMAND_PARSER(location) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._string = strdup(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._string = strdup(_tokens[ctxt.nextToken]); + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -525,10 +661,10 @@ DECLARE_COMMAND_PARSER(location) { DECLARE_COMMAND_PARSER(drop) { debugC(7, kDebugParser, "COMMAND_PARSER(drop) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._object = 4 + _objectsNames->lookup(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._object = 4 + _vm->_objectsNames->lookup(_tokens[ctxt.nextToken]); + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -538,10 +674,10 @@ DECLARE_COMMAND_PARSER(drop) { DECLARE_COMMAND_PARSER(call) { debugC(7, kDebugParser, "COMMAND_PARSER(call) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._callable = _callableNames->lookup(_tokens[_locParseCtxt.nextToken]) - 1; - _locParseCtxt.nextToken++; + ctxt.cmd->u._callable = _vm->_callableNames->lookup(_tokens[ctxt.nextToken]) - 1; + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -551,7 +687,7 @@ DECLARE_COMMAND_PARSER(call) { DECLARE_COMMAND_PARSER(simple) { debugC(7, kDebugParser, "COMMAND_PARSER(simple) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); addCommand(); } @@ -559,12 +695,12 @@ DECLARE_COMMAND_PARSER(simple) { DECLARE_COMMAND_PARSER(move) { debugC(7, kDebugParser, "COMMAND_PARSER(move) "); - createCommand(_locationParser->_lookup); + createCommand(_parser->_lookup); - _locParseCtxt.cmd->u._move.x = atoi(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; - _locParseCtxt.cmd->u._move.y = atoi(_tokens[_locParseCtxt.nextToken]); - _locParseCtxt.nextToken++; + ctxt.cmd->u._move.x = atoi(_tokens[ctxt.nextToken]); + ctxt.nextToken++; + ctxt.cmd->u._move.y = atoi(_tokens[ctxt.nextToken]); + ctxt.nextToken++; parseCommandFlags(); addCommand(); @@ -573,16 +709,16 @@ DECLARE_COMMAND_PARSER(move) { DECLARE_COMMAND_PARSER(endcommands) { debugC(7, kDebugParser, "COMMAND_PARSER(endcommands) "); - _locationParser->popTables(); + _parser->popTables(); // temporary trick to handle dialogue commands - _locParseCtxt.endcommands = true; + ctxt.endcommands = true; } -void Parallaction_ns::parseCommandFlags() { +void LocationParser_ns::parseCommandFlags() { - int _si = _locParseCtxt.nextToken; - CommandPtr cmd = _locParseCtxt.cmd; + int _si = ctxt.nextToken; + CommandPtr cmd = ctxt.cmd; if (!scumm_stricmp(_tokens[_si], "flags")) { _si++; @@ -595,11 +731,11 @@ void Parallaction_ns::parseCommandFlags() { cmd->_flagsOn |= kFlagsEnter; } else if (!scumm_strnicmp(_tokens[_si], "no", 2)) { - byte _al = _localFlagNames->lookup(&_tokens[_si][2]); + byte _al = _vm->_localFlagNames->lookup(&_tokens[_si][2]); assert(_al != Table::notFound); cmd->_flagsOff |= 1 << (_al - 1); } else { - byte _al = _localFlagNames->lookup(_tokens[_si]); + byte _al = _vm->_localFlagNames->lookup(_tokens[_si]); assert(_al != Table::notFound); cmd->_flagsOn |= 1 << (_al - 1); } @@ -622,11 +758,11 @@ void Parallaction_ns::parseCommandFlags() { cmd->_flagsOn |= kFlagsEnter; } else if (!scumm_strnicmp(_tokens[_si], "no", 2)) { - byte _al = _globalTable->lookup(&_tokens[_si][2]); + byte _al = _vm->_globalTable->lookup(&_tokens[_si][2]); assert(_al != Table::notFound); cmd->_flagsOff |= 1 << (_al - 1); } else { - byte _al = _globalTable->lookup(_tokens[_si]); + byte _al = _vm->_globalTable->lookup(_tokens[_si]); assert(_al != Table::notFound); cmd->_flagsOn |= 1 << (_al - 1); } @@ -637,23 +773,23 @@ void Parallaction_ns::parseCommandFlags() { } - _si = _locParseCtxt.nextToken; + _si = ctxt.nextToken; } -void Parallaction_ns::addCommand() { - _locParseCtxt.list->push_front(_locParseCtxt.cmd); // NOTE: command lists are written backwards in scripts +void LocationParser_ns::addCommand() { + ctxt.list->push_front(ctxt.cmd); // NOTE: command lists are written backwards in scripts } -void Parallaction_ns::createCommand(uint id) { +void LocationParser_ns::createCommand(uint id) { - _locParseCtxt.nextToken = 1; - _locParseCtxt.cmd = CommandPtr(new Command); - _locParseCtxt.cmd->_id = id; + ctxt.nextToken = 1; + ctxt.cmd = CommandPtr(new Command); + ctxt.cmd->_id = id; } -void Parallaction_ns::saveCommandForward(const char *name, CommandPtr cmd) { +void LocationParser_ns::saveCommandForward(const char *name, CommandPtr cmd) { assert(_numForwardedCommands < MAX_FORWARDS); strcpy(_forwardedCommands[_numForwardedCommands].name, name); @@ -662,9 +798,9 @@ void Parallaction_ns::saveCommandForward(const char *name, CommandPtr cmd) { _numForwardedCommands++; } -void Parallaction_ns::resolveCommandForwards() { +void LocationParser_ns::resolveCommandForwards() { for (uint i = 0; i < _numForwardedCommands; i++) { - _forwardedCommands[i].cmd->u._zone = findZone(_forwardedCommands[i].name); + _forwardedCommands[i].cmd->u._zone = _vm->findZone(_forwardedCommands[i].name); if (_forwardedCommands[i].cmd->u._zone == 0) { warning("Cannot find zone '%s' into current location script. This may be a bug in the original scripts.\n", _forwardedCommands[i].name); } @@ -672,17 +808,16 @@ void Parallaction_ns::resolveCommandForwards() { _numForwardedCommands = 0; } -void Parallaction_ns::parseCommands(Script &script, CommandList& list) { +void LocationParser_ns::parseCommands(CommandList& list) { debugC(5, kDebugParser, "parseCommands()"); - _locParseCtxt.list = &list; - _locParseCtxt.endcommands = false; - _locParseCtxt.script = &script; + ctxt.list = &list; + ctxt.endcommands = false; - _locationParser->pushTables(&_commandParsers, _commandsNames); + _parser->pushTables(&_commandParsers, _commandsNames); } -Dialogue *Parallaction_ns::parseDialogue(Script &script) { +Dialogue *LocationParser_ns::parseDialogue() { debugC(7, kDebugParser, "parseDialogue()"); uint16 numQuestions = 0; @@ -692,16 +827,16 @@ Dialogue *Parallaction_ns::parseDialogue(Script &script) { Table forwards(20); - script.readLineToken(true); + _script->readLineToken(true); while (scumm_stricmp(_tokens[0], "enddialogue")) { if (scumm_stricmp(_tokens[0], "Question")) continue; forwards.addData(_tokens[1]); - dialogue->_questions[numQuestions++] = parseQuestion(script); + dialogue->_questions[numQuestions++] = parseQuestion(); - script.readLineToken(true); + _script->readLineToken(true); } resolveDialogueForwards(dialogue, numQuestions, forwards); @@ -711,28 +846,28 @@ Dialogue *Parallaction_ns::parseDialogue(Script &script) { return dialogue; } -Question *Parallaction_ns::parseQuestion(Script &script) { +Question *LocationParser_ns::parseQuestion() { Question *question = new Question; assert(question); - question->_text = parseDialogueString(script); + question->_text = parseDialogueString(); - script.readLineToken(true); + _script->readLineToken(true); question->_mood = atoi(_tokens[0]); uint16 numAnswers = 0; - script.readLineToken(true); + _script->readLineToken(true); while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers - question->_answers[numAnswers] = parseAnswer(script); + question->_answers[numAnswers] = parseAnswer(); numAnswers++; } return question; } -Answer *Parallaction_ns::parseAnswer(Script &script) { +Answer *LocationParser_ns::parseAnswer() { Answer *answer = new Answer; assert(answer); @@ -744,11 +879,11 @@ Answer *Parallaction_ns::parseAnswer(Script &script) { if (!scumm_stricmp(_tokens[1], "global")) { token = 2; - flagNames = _globalTable; + flagNames = _vm->_globalTable; answer->_yesFlags |= kFlagsGlobal; } else { token = 1; - flagNames = _localFlagNames; + flagNames = _vm->_localFlagNames; } do { @@ -767,28 +902,29 @@ Answer *Parallaction_ns::parseAnswer(Script &script) { } - answer->_text = parseDialogueString(script); + answer->_text = parseDialogueString(); - script.readLineToken(true); + _script->readLineToken(true); answer->_mood = atoi(_tokens[0]); - answer->_following._name = parseDialogueString(script); + answer->_following._name = parseDialogueString(); - script.readLineToken(true); + _script->readLineToken(true); if (!scumm_stricmp(_tokens[0], "commands")) { - parseCommands(script, answer->_commands); - _locParseCtxt.endcommands = false; + parseCommands(answer->_commands); + ctxt.endcommands = false; do { - _locationParser->parseStatement(); - } while (!_locParseCtxt.endcommands); + _script->readLineToken(true); + _parser->parseStatement(); + } while (!ctxt.endcommands); - script.readLineToken(true); + _script->readLineToken(true); } return answer; } -void Parallaction_ns::resolveDialogueForwards(Dialogue *dialogue, uint numQuestions, Table &forwards) { +void LocationParser_ns::resolveDialogueForwards(Dialogue *dialogue, uint numQuestions, Table &forwards) { for (uint16 i = 0; i < numQuestions; i++) { Question *question = dialogue->_questions[i]; @@ -811,13 +947,13 @@ void Parallaction_ns::resolveDialogueForwards(Dialogue *dialogue, uint numQuesti } -char *Parallaction_ns::parseDialogueString(Script &script) { +char *LocationParser_ns::parseDialogueString() { char vC8[200]; char *vD0 = NULL; do { - vD0 = script.readLine(vC8, 200); + vD0 = _script->readLine(vC8, 200); if (vD0 == 0) return NULL; vD0 = Common::ltrim(vD0); @@ -833,7 +969,7 @@ char *Parallaction_ns::parseDialogueString(Script &script) { DECLARE_LOCATION_PARSER(endlocation) { debugC(7, kDebugParser, "LOCATION_PARSER(endlocation) "); - _locParseCtxt.end = true; + ctxt.end = true; } @@ -851,16 +987,16 @@ DECLARE_LOCATION_PARSER(location) { mask++; } - strcpy(_location._name, _tokens[1]); - switchBackground(_location._name, mask); + strcpy(_vm->_location._name, _tokens[1]); + _vm->switchBackground(_vm->_location._name, mask); if (_tokens[2][0] != '\0') { - _char._ani->_left = atoi(_tokens[2]); - _char._ani->_top = atoi(_tokens[3]); + _vm->_char._ani->_left = atoi(_tokens[2]); + _vm->_char._ani->_top = atoi(_tokens[3]); } if (_tokens[4][0] != '\0') { - _char._ani->_frame = atoi(_tokens[4]); + _vm->_char._ani->_frame = atoi(_tokens[4]); } } @@ -868,28 +1004,28 @@ DECLARE_LOCATION_PARSER(location) { DECLARE_LOCATION_PARSER(disk) { debugC(7, kDebugParser, "LOCATION_PARSER(disk) "); - _disk->selectArchive(_tokens[1]); + _vm->_disk->selectArchive(_tokens[1]); } DECLARE_LOCATION_PARSER(nodes) { debugC(7, kDebugParser, "LOCATION_PARSER(nodes) "); - parseWalkNodes(*_locParseCtxt.script, _location._walkNodes); + parseWalkNodes(_vm->_location._walkNodes); } DECLARE_LOCATION_PARSER(zone) { debugC(7, kDebugParser, "LOCATION_PARSER(zone) "); - parseZone(*_locParseCtxt.script, _location._zones, _tokens[1]); + parseZone(_vm->_location._zones, _tokens[1]); } DECLARE_LOCATION_PARSER(animation) { debugC(7, kDebugParser, "LOCATION_PARSER(animation) "); - parseAnimation(*_locParseCtxt.script, _location._animations, _tokens[1]); + parseAnimation(_vm->_location._animations, _tokens[1]); } @@ -898,7 +1034,7 @@ DECLARE_LOCATION_PARSER(localflags) { int _si = 1; while (_tokens[_si][0] != '\0') { - _localFlagNames->addData(_tokens[_si]); + _vm->_localFlagNames->addData(_tokens[_si]); _si++; } } @@ -907,28 +1043,28 @@ DECLARE_LOCATION_PARSER(localflags) { DECLARE_LOCATION_PARSER(commands) { debugC(7, kDebugParser, "LOCATION_PARSER(commands) "); - parseCommands(*_locParseCtxt.script, _location._commands); + parseCommands(_vm->_location._commands); } DECLARE_LOCATION_PARSER(acommands) { debugC(7, kDebugParser, "LOCATION_PARSER(acommands) "); - parseCommands(*_locParseCtxt.script, _location._aCommands); + parseCommands(_vm->_location._aCommands); } DECLARE_LOCATION_PARSER(flags) { debugC(7, kDebugParser, "LOCATION_PARSER(flags) "); - if ((getLocationFlags() & kFlagsVisited) == 0) { + if ((_vm->getLocationFlags() & kFlagsVisited) == 0) { // only for 1st visit - clearLocationFlags(kFlagsAll); + _vm->clearLocationFlags(kFlagsAll); int _si = 1; do { - byte _al = _localFlagNames->lookup(_tokens[_si]); - setLocationFlags(1 << (_al - 1)); + byte _al = _vm->_localFlagNames->lookup(_tokens[_si]); + _vm->setLocationFlags(1 << (_al - 1)); _si++; if (scumm_stricmp(_tokens[_si], "|")) break; @@ -941,23 +1077,23 @@ DECLARE_LOCATION_PARSER(flags) { DECLARE_LOCATION_PARSER(comment) { debugC(7, kDebugParser, "LOCATION_PARSER(comment) "); - _location._comment = parseComment(*_locParseCtxt.script); + _vm->_location._comment = parseComment(); } DECLARE_LOCATION_PARSER(endcomment) { debugC(7, kDebugParser, "LOCATION_PARSER(endcomment) "); - _location._endComment = parseComment(*_locParseCtxt.script); + _vm->_location._endComment = parseComment(); } DECLARE_LOCATION_PARSER(sound) { debugC(7, kDebugParser, "LOCATION_PARSER(sound) "); - if (getPlatform() == Common::kPlatformAmiga) { - strcpy(_location._soundFile, _tokens[1]); - _location._hasSound = true; + if (_vm->getPlatform() == Common::kPlatformAmiga) { + strcpy(_vm->_location._soundFile, _tokens[1]); + _vm->_location._hasSound = true; } } @@ -965,58 +1101,33 @@ DECLARE_LOCATION_PARSER(sound) { DECLARE_LOCATION_PARSER(music) { debugC(7, kDebugParser, "LOCATION_PARSER(music) "); - if (getPlatform() == Common::kPlatformAmiga) - _soundMan->setMusicFile(_tokens[1]); + if (_vm->getPlatform() == Common::kPlatformAmiga) + _vm->_soundMan->setMusicFile(_tokens[1]); } - -void Parallaction_ns::parseLocation(const char *filename) { - debugC(1, kDebugParser, "parseLocation('%s')", filename); - - allocateLocationSlot(filename); -// printf("got location slot #%i for %s\n", _currentLocationIndex, filename); +void LocationParser_ns::parse(Script *script) { _numForwardedCommands = 0; - Script *script = _disk->loadLocation(filename); - _locationParser->bind(script); - - // TODO: the following two lines are specific to Nippon Safes - // and should be moved into something like 'initializeParsing()' - _location._hasSound = false; + ctxt.end = false; + _script = script; + ctxt.filename = 0;//filename; - _locParseCtxt.end = false; - _locParseCtxt.script = script; - _locParseCtxt.filename = filename; - - _locationParser->pushTables(&_locationParsers, _locationStmt); + _parser->reset(); + _parser->pushTables(&_locationParsers, _locationStmt); do { - _locationParser->parseStatement(); - } while (!_locParseCtxt.end); - _locationParser->popTables(); - _locationParser->unbind(); - - delete script; + _script->readLineToken(true); + _parser->parseStatement(); + } while (!ctxt.end); + _parser->popTables(); resolveCommandForwards(); - - // this loads animation scripts - AnimationList::iterator it = _location._animations.begin(); - for ( ; it != _location._animations.end(); it++) { - if ((*it)->_scriptName) { - loadProgram(*it, (*it)->_scriptName); - } - } - - debugC(1, kDebugParser, "parseLocation('%s') done", filename); - return; } - -void Parallaction_ns::parseWalkNodes(Script& script, WalkNodeList &list) { +void LocationParser_ns::parseWalkNodes(WalkNodeList &list) { debugC(5, kDebugParser, "parseWalkNodes()"); - script.readLineToken(true); + _script->readLineToken(true); while (scumm_stricmp(_tokens[0], "ENDNODES")) { if (!scumm_stricmp(_tokens[0], "COORD")) { @@ -1029,146 +1140,159 @@ void Parallaction_ns::parseWalkNodes(Script& script, WalkNodeList &list) { list.push_front(v4); } - script.readLineToken(true); + _script->readLineToken(true); } debugC(5, kDebugParser, "parseWalkNodes() done"); return; } - -typedef OpcodeImpl<Parallaction_ns> OpcodeV1; -#define INSTRUCTION_PARSER(sig) OpcodeV1(this, &Parallaction_ns::instParse_##sig) -#define ZONE_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locZoneParse_##sig) -#define ANIM_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locAnimParse_##sig) -#define LOCATION_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locParse_##sig) -#define COMMAND_PARSER(sig) OpcodeV1(this, &Parallaction_ns::cmdParse_##sig) - -#define WARNING_PARSER(sig) OpcodeV1(this, &Parallaction_br::warning_##sig) - -void Parallaction_ns::initParsers() { - - _locationParser = new Parser; - - static const OpcodeV1 op0[] = { - INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition - INSTRUCTION_PARSER(animation), // on - INSTRUCTION_PARSER(animation), // off - INSTRUCTION_PARSER(x), - INSTRUCTION_PARSER(y), - INSTRUCTION_PARSER(z), - INSTRUCTION_PARSER(f), - INSTRUCTION_PARSER(loop), - INSTRUCTION_PARSER(null), // endloop - INSTRUCTION_PARSER(null), // show - INSTRUCTION_PARSER(inc), - INSTRUCTION_PARSER(inc), // dec - INSTRUCTION_PARSER(set), - INSTRUCTION_PARSER(put), - INSTRUCTION_PARSER(call), - INSTRUCTION_PARSER(null), // wait - INSTRUCTION_PARSER(animation), // start - INSTRUCTION_PARSER(sound), - INSTRUCTION_PARSER(move), - INSTRUCTION_PARSER(endscript) - }; - - uint i; - for (i = 0; i < ARRAYSIZE(op0); i++) - _instructionParsers.push_back(&op0[i]); - - - static const OpcodeV1 op2[] = { - WARNING_PARSER(unexpected), - COMMAND_PARSER(flags), // set - COMMAND_PARSER(flags), // clear - COMMAND_PARSER(zone), // start - COMMAND_PARSER(zone), // speak - COMMAND_PARSER(zone), // get - COMMAND_PARSER(location), // location - COMMAND_PARSER(zone), // open - COMMAND_PARSER(zone), // close - COMMAND_PARSER(zone), // on - COMMAND_PARSER(zone), // off - COMMAND_PARSER(call), // call - COMMAND_PARSER(flags), // toggle - COMMAND_PARSER(drop), // drop - COMMAND_PARSER(simple), // quit - COMMAND_PARSER(move), // move - COMMAND_PARSER(zone), // stop - COMMAND_PARSER(endcommands), // endcommands - COMMAND_PARSER(endcommands) // endzone - }; - - for (i = 0; i < ARRAYSIZE(op2); i++) - _commandParsers.push_back(&op2[i]); - - - static const OpcodeV1 op4[] = { - WARNING_PARSER(unexpected), - LOCATION_PARSER(endlocation), - LOCATION_PARSER(location), - LOCATION_PARSER(disk), - LOCATION_PARSER(nodes), - LOCATION_PARSER(zone), - LOCATION_PARSER(animation), - LOCATION_PARSER(localflags), - LOCATION_PARSER(commands), - LOCATION_PARSER(acommands), - LOCATION_PARSER(flags), - LOCATION_PARSER(comment), - LOCATION_PARSER(endcomment), - LOCATION_PARSER(sound), - LOCATION_PARSER(music) - }; - - for (i = 0; i < ARRAYSIZE(op4); i++) - _locationParsers.push_back(&op4[i]); - - static const OpcodeV1 op5[] = { - WARNING_PARSER(unexpected), - ZONE_PARSER(limits), - ZONE_PARSER(moveto), - ZONE_PARSER(type), - ZONE_PARSER(commands), - ZONE_PARSER(label), - ZONE_PARSER(flags), - ZONE_PARSER(endzone) - }; - - for (i = 0; i < ARRAYSIZE(op5); i++) - _locationZoneParsers.push_back(&op5[i]); - - static const OpcodeV1 op6[] = { - WARNING_PARSER(unexpected), - ANIM_PARSER(script), - ANIM_PARSER(commands), - ANIM_PARSER(type), - ANIM_PARSER(label), - ANIM_PARSER(flags), - ANIM_PARSER(file), - ANIM_PARSER(position), - ANIM_PARSER(moveto), - ANIM_PARSER(endanimation) - }; - - for (i = 0; i < ARRAYSIZE(op6); i++) - _locationAnimParsers.push_back(&op6[i]); - +/* +typedef OpcodeImpl<ProgramParser_ns> OpcodeV1; +#define INSTRUCTION_PARSER(sig) OpcodeV1(this, &ProgramParser_ns::instParse_##sig) + +typedef OpcodeImpl<LocationParser_ns> OpcodeV2; +#define ZONE_PARSER(sig) OpcodeV2(this, &LocationParser_ns::locZoneParse_##sig) +#define ANIM_PARSER(sig) OpcodeV2(this, &LocationParser_ns::locAnimParse_##sig) +#define LOCATION_PARSER(sig) OpcodeV2(this, &LocationParser_ns::locParse_##sig) +#define COMMAND_PARSER(sig) OpcodeV2(this, &LocationParser_ns::cmdParse_##sig) + +#define WARNING_PARSER(sig) OpcodeV2(this, &LocationParser_br::warning_##sig) +*/ + +#define SetOpcodeTable(x) table = &x; + + +typedef Common::Functor0Mem<void, ProgramParser_ns> OpcodeV1; +#define SetOpcodeTable(x) table = &x; +#define INSTRUCTION_PARSER(sig) table->push_back(new OpcodeV1(this, &ProgramParser_ns::instParse_##sig)) + +typedef Common::Functor0Mem<void, LocationParser_ns> OpcodeV2; +#define ZONE_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_ns::locZoneParse_##sig)) +#define ANIM_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_ns::locAnimParse_##sig)) +#define LOCATION_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_ns::locParse_##sig)) +#define COMMAND_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_ns::cmdParse_##sig)) + +#define WARNING_PARSER(sig) table->push_back(new OpcodeV2(this, &LocationParser_br::warning_##sig)) + + +void LocationParser_ns::init() { + + _parser = new Parser; + + _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_ns), _zoneFlagNamesRes_ns); + _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_ns), _zoneTypeNamesRes_ns); + _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_ns), _commandsNamesRes_ns); + _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_ns), _locationStmtRes_ns); + _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_ns), _locationZoneStmtRes_ns); + _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_ns), _locationAnimStmtRes_ns); + + Common::Array<const Opcode*> *table = 0; + + SetOpcodeTable(_commandParsers); + WARNING_PARSER(unexpected); + COMMAND_PARSER(flags); // set + COMMAND_PARSER(flags); // clear + COMMAND_PARSER(zone); // start + COMMAND_PARSER(zone); // speak + COMMAND_PARSER(zone); // get + COMMAND_PARSER(location); // location + COMMAND_PARSER(zone); // open + COMMAND_PARSER(zone); // close + COMMAND_PARSER(zone); // on + COMMAND_PARSER(zone); // off + COMMAND_PARSER(call); // call + COMMAND_PARSER(flags); // toggle + COMMAND_PARSER(drop); // drop + COMMAND_PARSER(simple); // quit + COMMAND_PARSER(move); // move + COMMAND_PARSER(zone); // stop + COMMAND_PARSER(endcommands); // endcommands + COMMAND_PARSER(endcommands); // endzone + + SetOpcodeTable(_locationParsers); + WARNING_PARSER(unexpected); + LOCATION_PARSER(endlocation); + LOCATION_PARSER(location); + LOCATION_PARSER(disk); + LOCATION_PARSER(nodes); + LOCATION_PARSER(zone); + LOCATION_PARSER(animation); + LOCATION_PARSER(localflags); + LOCATION_PARSER(commands); + LOCATION_PARSER(acommands); + LOCATION_PARSER(flags); + LOCATION_PARSER(comment); + LOCATION_PARSER(endcomment); + LOCATION_PARSER(sound); + LOCATION_PARSER(music); + + SetOpcodeTable(_locationZoneParsers); + WARNING_PARSER(unexpected); + ZONE_PARSER(limits); + ZONE_PARSER(moveto); + ZONE_PARSER(type); + ZONE_PARSER(commands); + ZONE_PARSER(label); + ZONE_PARSER(flags); + ZONE_PARSER(endzone); + + SetOpcodeTable(_locationAnimParsers); + WARNING_PARSER(unexpected); + ANIM_PARSER(script); + ANIM_PARSER(commands); + ANIM_PARSER(type); + ANIM_PARSER(label); + ANIM_PARSER(flags); + ANIM_PARSER(file); + ANIM_PARSER(position); + ANIM_PARSER(moveto); + ANIM_PARSER(endanimation); + +} + +void ProgramParser_ns::init() { + + _parser = new Parser; + + _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes_ns), _instructionNamesRes_ns); + + Common::Array<const Opcode*> *table = 0; + SetOpcodeTable(_instructionParsers); + INSTRUCTION_PARSER(defLocal); // invalid opcode -> local definition + INSTRUCTION_PARSER(animation); // on + INSTRUCTION_PARSER(animation); // off + INSTRUCTION_PARSER(x); + INSTRUCTION_PARSER(y); + INSTRUCTION_PARSER(z); + INSTRUCTION_PARSER(f); + INSTRUCTION_PARSER(loop); + INSTRUCTION_PARSER(null); // endloop + INSTRUCTION_PARSER(null); // show + INSTRUCTION_PARSER(inc); + INSTRUCTION_PARSER(inc); // dec + INSTRUCTION_PARSER(set); + INSTRUCTION_PARSER(put); + INSTRUCTION_PARSER(call); + INSTRUCTION_PARSER(null); // wait + INSTRUCTION_PARSER(animation); // start + INSTRUCTION_PARSER(sound); + INSTRUCTION_PARSER(move); + INSTRUCTION_PARSER(endscript); } // // a comment can appear both at location and Zone levels // comments are displayed into rectangles on the screen // -char *Parallaction_ns::parseComment(Script &script) { +char *LocationParser_ns::parseComment() { char _tmp_comment[1000] = "\0"; char *v194; do { char v190[400]; - v194 = script.readLine(v190, 400); + v194 = _script->readLine(v190, 400); v194[strlen(v194)-1] = '\0'; if (!scumm_stricmp(v194, "endtext")) @@ -1192,24 +1316,24 @@ DECLARE_ZONE_PARSER(null) { DECLARE_ZONE_PARSER(endzone) { debugC(7, kDebugParser, "ZONE_PARSER(endzone) "); - _locationParser->popTables(); + _parser->popTables(); } DECLARE_ZONE_PARSER(limits) { debugC(7, kDebugParser, "ZONE_PARSER(limits) "); - _locParseCtxt.z->_left = atoi(_tokens[1]); - _locParseCtxt.z->_top = atoi(_tokens[2]); - _locParseCtxt.z->_right = atoi(_tokens[3]); - _locParseCtxt.z->_bottom = atoi(_tokens[4]); + ctxt.z->_left = atoi(_tokens[1]); + ctxt.z->_top = atoi(_tokens[2]); + ctxt.z->_right = atoi(_tokens[3]); + ctxt.z->_bottom = atoi(_tokens[4]); } DECLARE_ZONE_PARSER(moveto) { debugC(7, kDebugParser, "ZONE_PARSER(moveto) "); - _locParseCtxt.z->_moveTo.x = atoi(_tokens[1]); - _locParseCtxt.z->_moveTo.y = atoi(_tokens[2]); + ctxt.z->_moveTo.x = atoi(_tokens[1]); + ctxt.z->_moveTo.y = atoi(_tokens[2]); } @@ -1217,22 +1341,22 @@ DECLARE_ZONE_PARSER(type) { debugC(7, kDebugParser, "ZONE_PARSER(type) "); if (_tokens[2][0] != '\0') { - _locParseCtxt.z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16; + ctxt.z->_type = (4 + _vm->_objectsNames->lookup(_tokens[2])) << 16; } int16 _si = _zoneTypeNames->lookup(_tokens[1]); if (_si != Table::notFound) { - _locParseCtxt.z->_type |= 1 << (_si - 1); - parseZoneTypeBlock(*_locParseCtxt.script, _locParseCtxt.z); + ctxt.z->_type |= 1 << (_si - 1); + parseZoneTypeBlock(ctxt.z); } - _locationParser->popTables(); + _parser->popTables(); } DECLARE_ZONE_PARSER(commands) { debugC(7, kDebugParser, "ZONE_PARSER(commands) "); - parseCommands(*_locParseCtxt.script, _locParseCtxt.z->_commands); + parseCommands(ctxt.z->_commands); } @@ -1240,7 +1364,7 @@ DECLARE_ZONE_PARSER(label) { debugC(7, kDebugParser, "ZONE_PARSER(label) "); // printf("label: %s", _tokens[1]); - _locParseCtxt.z->_label = _gfx->renderFloatingLabel(_labelFont, _tokens[1]); + ctxt.z->_label = _vm->_gfx->renderFloatingLabel(_vm->_labelFont, _tokens[1]); } @@ -1252,15 +1376,15 @@ DECLARE_ZONE_PARSER(flags) { do { char _al = _zoneFlagNames->lookup(_tokens[_si]); _si++; - _locParseCtxt.z->_flags |= 1 << (_al - 1); + ctxt.z->_flags |= 1 << (_al - 1); } while (!scumm_stricmp(_tokens[_si++], "|")); } -void Parallaction_ns::parseZone(Script &script, ZoneList &list, char *name) { +void LocationParser_ns::parseZone(ZoneList &list, char *name) { debugC(5, kDebugParser, "parseZone(name: %s)", name); - if (findZone(name)) { - script.skip("endzone"); + if (_vm->findZone(name)) { + _script->skip("endzone"); return; } @@ -1268,12 +1392,11 @@ void Parallaction_ns::parseZone(Script &script, ZoneList &list, char *name) { strncpy(z->_name, name, ZONENAME_LENGTH); - _locParseCtxt.z = z; - _locParseCtxt.script = &script; + ctxt.z = z; list.push_front(z); - _locationParser->pushTables(&_locationZoneParsers, _locationZoneStmt); + _parser->pushTables(&_locationZoneParsers, _locationZoneStmt); return; } @@ -1281,7 +1404,7 @@ void Parallaction_ns::parseZone(Script &script, ZoneList &list, char *name) { -void Parallaction_ns::parseGetData(Script &script, ZonePtr z) { +void LocationParser_ns::parseGetData(ZonePtr z) { GetData *data = new GetData; @@ -1291,20 +1414,20 @@ void Parallaction_ns::parseGetData(Script &script, ZonePtr z) { bool visible = (z->_flags & kFlagsRemove) == 0; - GfxObj *obj = _gfx->loadGet(_tokens[1]); + GfxObj *obj = _vm->_gfx->loadGet(_tokens[1]); obj->frame = 0; obj->x = z->_left; obj->y = z->_top; - _gfx->showGfxObj(obj, visible); + _vm->_gfx->showGfxObj(obj, visible); data->gfxobj = obj; } if (!scumm_stricmp(_tokens[0], "icon")) { - data->_icon = 4 + _objectsNames->lookup(_tokens[1]); + data->_icon = 4 + _vm->_objectsNames->lookup(_tokens[1]); } - script.readLineToken(true); + _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone")); z->u.get = data; @@ -1312,7 +1435,7 @@ void Parallaction_ns::parseGetData(Script &script, ZonePtr z) { } -void Parallaction_ns::parseExamineData(Script &script, ZonePtr z) { +void LocationParser_ns::parseExamineData(ZonePtr z) { ExamineData *data = new ExamineData; @@ -1322,10 +1445,10 @@ void Parallaction_ns::parseExamineData(Script &script, ZonePtr z) { data->_filename = strdup(_tokens[1]); } if (!scumm_stricmp(_tokens[0], "desc")) { - data->_description = parseComment(script); + data->_description = parseComment(); } - script.readLineToken(true); + _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone")); z->u.examine = data; @@ -1333,16 +1456,16 @@ void Parallaction_ns::parseExamineData(Script &script, ZonePtr z) { } -void Parallaction_ns::parseDoorData(Script &script, ZonePtr z) { +void LocationParser_ns::parseDoorData(ZonePtr z) { DoorData *data = new DoorData; do { if (!scumm_stricmp(_tokens[0], "slidetext")) { - strcpy(_slideText[0], _tokens[1]); + strcpy(_vm->_location._slideText[0], _tokens[1]); // printf("%s\t", _slideText[0]); - strcpy(_slideText[1], _tokens[2]); + strcpy(_vm->_location._slideText[1], _tokens[2]); } if (!scumm_stricmp(_tokens[0], "location")) { @@ -1354,11 +1477,11 @@ void Parallaction_ns::parseDoorData(Script &script, ZonePtr z) { uint16 frame = (z->_flags & kFlagsClosed ? 0 : 1); - GfxObj *obj = _gfx->loadDoor(_tokens[1]); + GfxObj *obj = _vm->_gfx->loadDoor(_tokens[1]); obj->frame = frame; obj->x = z->_left; obj->y = z->_top; - _gfx->showGfxObj(obj, true); + _vm->_gfx->showGfxObj(obj, true); data->gfxobj = obj; } @@ -1369,7 +1492,7 @@ void Parallaction_ns::parseDoorData(Script &script, ZonePtr z) { data->_startFrame = atoi(_tokens[3]); } - script.readLineToken(true); + _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone")); z->u.door = data; @@ -1377,30 +1500,30 @@ void Parallaction_ns::parseDoorData(Script &script, ZonePtr z) { } -void Parallaction_ns::parseMergeData(Script &script, ZonePtr z) { +void LocationParser_ns::parseMergeData(ZonePtr z) { MergeData *data = new MergeData; do { if (!scumm_stricmp(_tokens[0], "obj1")) { - data->_obj1 = 4 + _objectsNames->lookup(_tokens[1]); + data->_obj1 = 4 + _vm->_objectsNames->lookup(_tokens[1]); } if (!scumm_stricmp(_tokens[0], "obj2")) { - data->_obj2 = 4 + _objectsNames->lookup(_tokens[1]); + data->_obj2 = 4 + _vm->_objectsNames->lookup(_tokens[1]); } if (!scumm_stricmp(_tokens[0], "newobj")) { - data->_obj3 = 4 + _objectsNames->lookup(_tokens[1]); + data->_obj3 = 4 + _vm->_objectsNames->lookup(_tokens[1]); } - script.readLineToken(true); + _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone")); z->u.merge = data; } -void Parallaction_ns::parseHearData(Script &script, ZonePtr z) { +void LocationParser_ns::parseHearData(ZonePtr z) { HearData *data = new HearData; @@ -1414,14 +1537,14 @@ void Parallaction_ns::parseHearData(Script &script, ZonePtr z) { data->_freq = atoi(_tokens[1]); } - script.readLineToken(true); + _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone")); z->u.hear = data; } -void Parallaction_ns::parseSpeakData(Script &script, ZonePtr z) { +void LocationParser_ns::parseSpeakData(ZonePtr z) { SpeakData *data = new SpeakData; @@ -1431,10 +1554,10 @@ void Parallaction_ns::parseSpeakData(Script &script, ZonePtr z) { strcpy(data->_name, _tokens[1]); } if (!scumm_stricmp(_tokens[0], "Dialogue")) { - data->_dialogue = parseDialogue(script); + data->_dialogue = parseDialogue(); } - script.readLineToken(true); + _script->readLineToken(true); } while (scumm_stricmp(_tokens[0], "endzone")); z->u.speak = data; @@ -1442,37 +1565,37 @@ void Parallaction_ns::parseSpeakData(Script &script, ZonePtr z) { } -void Parallaction_ns::parseZoneTypeBlock(Script &script, ZonePtr z) { +void LocationParser_ns::parseZoneTypeBlock(ZonePtr z) { debugC(7, kDebugParser, "parseZoneTypeBlock(name: %s, type: %x)", z->_name, z->_type); switch (z->_type & 0xFFFF) { case kZoneExamine: // examine Zone alloc - parseExamineData(script, z); + parseExamineData(z); break; case kZoneDoor: // door Zone alloc - parseDoorData(script, z); + parseDoorData(z); break; case kZoneGet: // get Zone alloc - parseGetData(script, z); + parseGetData(z); break; case kZoneMerge: // merge Zone alloc - parseMergeData(script, z); + parseMergeData(z); break; case kZoneHear: // hear Zone alloc - parseHearData(script, z); + parseHearData(z); break; case kZoneSpeak: // speak Zone alloc - parseSpeakData(script, z); + parseSpeakData(z); break; default: // eats up 'ENDZONE' line for unprocessed zone types - script.readLineToken(true); + _script->readLineToken(true); break; } diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp index 53d370a0a8..2c5cf281dd 100644 --- a/engines/parallaction/staticres.cpp +++ b/engines/parallaction/staticres.cpp @@ -29,23 +29,23 @@ namespace Parallaction { -byte Parallaction_ns::_mouseArrow[256] = { - 0x12, 0x11, 0x11, 0x11, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x11, 0x13, 0x12, 0x12, 0x00, - 0x13, 0x12, 0x12, 0x11, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, - 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x13, 0x13, 0x13, 0x12, 0x00, - 0x13, 0x00, 0x12, 0x00, 0x13, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, - 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, - 0x13, 0x13, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, - 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x13, 0x12, 0x12, 0x00, - 0x00, 0x12, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x11, 0x11, 0x00, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x11, 0x00, - 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x11, - 0x12, 0x12, 0x12, 0x00, 0x12, 0x12, 0x12, 0x00, 0x13, 0x12, 0x12, 0x00, 0x00, 0x12, 0x13, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +byte Parallaction_ns::_resMouseArrow[256] = { + 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x11, 0x00, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x12, 0x12, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -216,80 +216,6 @@ byte _amigaTopazFont[2600] = { }; - -const char *_zoneFlagNamesRes_ns[] = { - "closed", - "active", - "remove", - "acting", - "locked", - "fixed", - "noname", - "nomasked", - "looping", - "added", - "character", - "nowalk" -}; - -const char *_zoneTypeNamesRes_ns[] = { - "examine", - "door", - "get", - "merge", - "taste", - "hear", - "feel", - "speak", - "none", - "trap", - "yourself", - "Command" -}; - -const char *_commandsNamesRes_ns[] = { - "set", - "clear", - "start", - "speak", - "get", - "location", - "open", - "close", - "on", - "off", - "call", - "toggle", - "drop", - "quit", - "move", - "stop", - "endcommands", - "endzone" -}; - -const char *_instructionNamesRes_ns[] = { - "on", - "off", - "x", - "y", - "z", - "f", - "loop", - "endloop", - "show", - "inc", - "dec", - "set", - "put", - "call", - "wait", - "start", - "sound", - "move", - "endscript" -}; - const char *_callableNamesRes_ns[] = { "Projector", "HBOff", @@ -318,160 +244,6 @@ const char *_callableNamesRes_ns[] = { "TestResult" }; -const char *_locationStmtRes_ns[] = { - "endlocation", - "location", - "disk", - "nodes", - "zone", - "animation", - "localflags", - "commands", - "acommands", - "flags", - "comment", - "endcomment", - "sound", - "music" -}; - -const char *_locationZoneStmtRes_ns[] = { - "limits", - "moveto", - "type", - "commands", - "label", - "flags", - "endzone" -}; - -const char *_locationAnimStmtRes_ns[] = { - "script", - "commands", - "type", - "label", - "flags", - "file", - "position", - "moveto", - "endanimation" -}; - -const char *_zoneTypeNamesRes_br[] = { - "examine", - "door", - "get", - "merge", - "taste", - "hear", - "feel", - "speak", - "none", - "trap", - "you", - "command", - "path", - "box" -}; - -const char *_zoneFlagNamesRes_br[] = { - "closed", - "active", - "remove", - "acting", - "locked", - "fixed", - "noname", - "nomasked", - "looping", - "added", - "character", - "nowalk", - "yourself", - "scaled", - "selfuse" -}; - -const char *_instructionNamesRes_br[] = { - "on", - "off", - "x", - "y", - "z", - "f", - "loop", - "endloop", - "show", - "inc", - "dec", - "set", - "put", - "call", - "wait", - "start", - "process", - "move", - "color", - "sound", - "mask", - "print", - "text", - "mul", - "div", - "if", - "dummy", - "dummy", - "endif", - "stop", - "endscript" -}; - -const char *_commandsNamesRes_br[] = { - "set", - "clear", - "start", - "speak", - "get", - "location", - "open", - "close", - "on", - "off", - "call", - "toggle", - "drop", - "quit", - "move", - "stop", - "character", - "followme", - "onmouse", - "offmouse", - "add", - "leave", - "inc", - "dec", - "test", - "dummy", - "dummy", - "let", - "music", - "fix", - "unfix", - "zeta", - "scroll", - "swap", - "give", - "text", - "part", - "dummy", - "return", - "onsave", - "offsave", - "endcommands", - "ifchar", - "endif" -}; const char *_callableNamesRes_br[] = { "blufade", @@ -482,72 +254,6 @@ const char *_callableNamesRes_br[] = { "password" }; -const char *_audioCommandsNamesRes_br[] = { - "play", - "stop", - "pause", - "channel_level", - "fadein", - "fadeout", - "volume", - " ", - "faderate", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "loop" -}; - -const char *_locationStmtRes_br[] = { - "character", - "endlocation", - "ifchar", - "endif", - "location", - "mask", - "path", - "disk", - "localflags", - "commands", - "escape", - "acommands", - "flags", - "comment", - "endcomment", - "zone", - "animation", - "zeta", - "music", - "sound" -}; - -const char *_locationZoneStmtRes_br[] = { - "endzone", - "limits", - "moveto", - "type", - "commands", - "label", - "flags" -}; - -const char *_locationAnimStmtRes_br[] = { - "endanimation", - "endzone", - "script", - "commands", - "type", - "label", - "flags", - "file", - "position", - "moveto" -}; - const char *_dinoName = "dino"; const char *_donnaName = "donna"; const char *_doughName = "dough"; @@ -629,20 +335,13 @@ const Parallaction_br::Callable Parallaction_br::_dosCallables[] = { void Parallaction_ns::initResources() { - _zoneFlagNamesRes = _zoneFlagNamesRes_ns; - _zoneTypeNamesRes = _zoneTypeNamesRes_ns; - _commandsNamesRes = _commandsNamesRes_ns; +// _zoneFlagNamesRes = _zoneFlagNamesRes_ns; +// _zoneTypeNamesRes = _zoneTypeNamesRes_ns; +// _commandsNamesRes = _commandsNamesRes_ns; _callableNamesRes = _callableNamesRes_ns; - _instructionNamesRes = _instructionNamesRes_ns; +// _instructionNamesRes = _instructionNamesRes_ns; _callableNames = new Table(ARRAYSIZE(_callableNamesRes_ns), _callableNamesRes_ns); - _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes_ns), _instructionNamesRes_ns); - _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_ns), _zoneFlagNamesRes_ns); - _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_ns), _zoneTypeNamesRes_ns); - _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_ns), _commandsNamesRes_ns); - _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_ns), _locationStmtRes_ns); - _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_ns), _locationZoneStmtRes_ns); - _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_ns), _locationAnimStmtRes_ns); _localFlagNames = new FixedTable(NUM_LOCATIONS, 1); _localFlagNames->addData("visited"); @@ -657,22 +356,14 @@ void Parallaction_ns::initResources() { void Parallaction_br::initResources() { - _zoneFlagNamesRes = _zoneFlagNamesRes_br; - _zoneTypeNamesRes = _zoneTypeNamesRes_br; - _commandsNamesRes = _commandsNamesRes_br; +// _zoneFlagNamesRes = _zoneFlagNamesRes_br; +// _zoneTypeNamesRes = _zoneTypeNamesRes_br; +// _commandsNamesRes = _commandsNamesRes_br; _callableNamesRes = _callableNamesRes_br; - _instructionNamesRes = _instructionNamesRes_br; - _audioCommandsNamesRes = _audioCommandsNamesRes_br; +// _instructionNamesRes = _instructionNamesRes_br; +// _audioCommandsNamesRes = _audioCommandsNamesRes_br; _callableNames = new Table(ARRAYSIZE(_callableNamesRes_br), _callableNamesRes_br); - _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes_br), _instructionNamesRes_br); - _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_br), _zoneFlagNamesRes_br); - _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_br), _zoneTypeNamesRes_br); - _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_br), _commandsNamesRes_br); - _audioCommandsNames = new Table(ARRAYSIZE(_audioCommandsNamesRes_br), _audioCommandsNamesRes_br); - _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_br), _locationStmtRes_br); - _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_br), _locationZoneStmtRes_br); - _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_br), _locationAnimStmtRes_br); _localFlagNames = new FixedTable(NUM_LOCATIONS, 2); _localFlagNames->addData("visited"); diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index 52b921d000..96d901fbba 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -31,7 +31,6 @@ #include "saga/events.h" #include "saga/isomap.h" #include "saga/objectmap.h" -#include "saga/sagaresnames.h" #include "saga/rscfile.h" #include "saga/script.h" #include "saga/sndres.h" @@ -997,7 +996,7 @@ void Actor::createDrawOrderList() { } bool Actor::getSpriteParams(CommonObjectData *commonObjectData, int &frameNumber, SpriteList *&spriteList) { - if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) { + if (_vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP) { if (!(commonObjectData->_flags & kProtagonist)){ // warning("not protagonist"); return false; diff --git a/engines/saga/actor_walk.cpp b/engines/saga/actor_walk.cpp index 0c573c0c40..d62c1c61d7 100644 --- a/engines/saga/actor_walk.cpp +++ b/engines/saga/actor_walk.cpp @@ -30,7 +30,6 @@ #include "saga/events.h" #include "saga/isomap.h" #include "saga/objectmap.h" -#include "saga/sagaresnames.h" #include "saga/script.h" #include "saga/sound.h" #include "saga/scene.h" @@ -209,7 +208,7 @@ void Actor::updateActorsScene(int actorsEntrance) { actor->_finalTarget = actor->_location; _centerActor = _protagonist = actor; } else if (_vm->getGameType() == GType_ITE && - _vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) { + _vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP) { continue; } @@ -416,7 +415,7 @@ void Actor::handleActions(int msec, bool setup) { speed = 4; } - if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) { + if (_vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP) { speed = 2; } diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index b7d2a3aa39..9c897d8ebc 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -36,7 +36,6 @@ #include "saga/rscfile.h" #include "saga/interface.h" #include "saga/scene.h" -#include "saga/sagaresnames.h" namespace Saga { struct SAGAGameDescription { @@ -55,18 +54,15 @@ struct SAGAGameDescription { const GamePatchDescription *patchDescriptions; }; -const bool SagaEngine::isBigEndian() const { return (_gameDescription->features & GF_BIG_ENDIAN_DATA) != 0; } -const bool SagaEngine::isMacResources() const { return (getPlatform() == Common::kPlatformMacintosh); } +bool SagaEngine::isBigEndian() const { return (_gameDescription->features & GF_BIG_ENDIAN_DATA) != 0; } +bool SagaEngine::isMacResources() const { return (getPlatform() == Common::kPlatformMacintosh); } const GameResourceDescription *SagaEngine::getResourceDescription() { return _gameDescription->resourceDescription; } const GameSoundInfo *SagaEngine::getVoiceInfo() const { return _gameDescription->voiceInfo; } const GameSoundInfo *SagaEngine::getSfxInfo() const { return _gameDescription->sfxInfo; } const GameSoundInfo *SagaEngine::getMusicInfo() const { static GameSoundInfo musicInfo; musicInfo.resourceType = kSoundPCM; - musicInfo.frequency = 11025; musicInfo.sampleBits = 16; - // The digital music in the ITE Mac demo version is not stereo - musicInfo.stereo = _gameDescription->gameType == GID_ITE_MACDEMO2 ? false : true; musicInfo.isBigEndian = false; musicInfo.isSigned = true; diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h index 0017f34957..cbc3152f70 100644 --- a/engines/saga/detection_tables.h +++ b/engines/saga/detection_tables.h @@ -28,71 +28,81 @@ namespace Saga { static const GameResourceDescription ITE_Resources = { - RID_ITE_SCENE_LUT, // Scene lookup table RN - RID_ITE_SCRIPT_LUT, // Script lookup table RN - RID_ITE_MAIN_PANEL, - RID_ITE_CONVERSE_PANEL, - RID_ITE_OPTION_PANEL, - 0, // Warning panel (IHNM only) - 0, // Warning panel sprites (IHNM only) - RID_ITE_MAIN_SPRITES, - RID_ITE_MAIN_PANEL_SPRITES, - 0, // Option panel sprites (IHNM only) - RID_ITE_DEFAULT_PORTRAITS, - 0, // Psychic profile background (IHNM only) - RID_ITE_MAIN_STRINGS, - RID_ITE_ACTOR_NAMES + 1806, // Scene lookup table RN + 216, // Script lookup table RN + 3, // Main panel + 4, // Converse panel + 5, // Option panel + 6, // Main sprites + 7, // Main panel sprites + 35, // Main strings + // ITE specific resources + 36, // Actor names + 125, // Default portraits + // IHNM specific resources + 0, // Option panel sprites + 0, // Warning panel + 0, // Warning panel sprites + 0 // Psychic profile background }; +// FIXME: Option panel should be 4 but it is an empty resource. +// Proper fix would be to not load the options panel when the demo is running static const GameResourceDescription ITEDemo_Resources = { - RID_ITEDEMO_SCENE_LUT, // Scene lookup table RN - RID_ITEDEMO_SCRIPT_LUT, // Script lookup table RN - RID_ITEDEMO_MAIN_PANEL, - RID_ITEDEMO_CONVERSE_PANEL, - RID_ITEDEMO_OPTION_PANEL, - 0, // Warning panel (IHNM only) - 0, // Warning panel sprites (IHNM only) - RID_ITEDEMO_MAIN_SPRITES, - RID_ITEDEMO_MAIN_PANEL_SPRITES, - 0, // Option panel sprites (IHNM only) - RID_ITEDEMO_DEFAULT_PORTRAITS, - 0, // Psychic profile background (IHNM only) - RID_ITEDEMO_MAIN_STRINGS, - RID_ITEDEMO_ACTOR_NAMES + 318, // Scene lookup table RN + 146, // Script lookup table RN + 2, // Main panel + 3, // Converse panel + 3, // Option panel + 5, // Main sprites + 6, // Main panel sprites + 8, // Main strings + // ITE specific resources + 9, // Actor names + 80, // Default portraits + // IHNM specific resources + 0, // Option panel sprites + 0, // Warning panel + 0, // Warning panel sprites + 0 // Psychic profile background }; static const GameResourceDescription IHNM_Resources = { - RID_IHNM_SCENE_LUT, // Scene lookup table RN - RID_IHNM_SCRIPT_LUT, // Script lookup table RN - RID_IHNM_MAIN_PANEL, - RID_IHNM_CONVERSE_PANEL, - RID_IHNM_OPTION_PANEL, - RID_IHNM_WARNING_PANEL, - RID_IHNM_WARNING_PANEL_SPRITES, - RID_IHNM_MAIN_SPRITES, - RID_IHNM_MAIN_PANEL_SPRITES, - RID_IHNM_OPTION_PANEL_SPRITES, - 0, // Default portraits (ITE only) - RID_IHNM_PROFILE_BG, - RID_IHNM_MAIN_STRINGS, - 0 // Actors strings (ITE only) + 1272, // Scene lookup table RN + 29, // Script lookup table RN + 9, // Main panel + 10, // Converse panel + 15, // Option panel + 12, // Main sprites + 12, // Main panel sprites + 21, // Main strings + // ITE specific resources + 0, // Actor names + 0, // Default portraits + // IHNM specific resources + 16, // Option panel sprites + 17, // Warning panel + 18, // Warning panel sprites + 20 // Psychic profile background }; static const GameResourceDescription IHNMDEMO_Resources = { - RID_IHNMDEMO_SCENE_LUT, // Scene lookup table RN - RID_IHNMDEMO_SCRIPT_LUT, // Script lookup table RN - RID_IHNMDEMO_MAIN_PANEL, - RID_IHNMDEMO_CONVERSE_PANEL, - RID_IHNMDEMO_OPTION_PANEL, - RID_IHNMDEMO_WARNING_PANEL, - RID_IHNMDEMO_WARNING_PANEL_SPRITES, - RID_IHNMDEMO_MAIN_SPRITES, - RID_IHNMDEMO_MAIN_PANEL_SPRITES, - RID_IHNMDEMO_OPTION_PANEL_SPRITES, - 0, // Default portraits (ITE only) - RID_IHNMDEMO_PROFILE_BG, - RID_IHNMDEMO_MAIN_STRINGS, - 0 // Actors strings (ITE only) + 286, // Scene lookup table RN + 18, // Script lookup table RN + 5, // Main panel + 6, // Converse panel + 10, // Option panel + 7, // Main sprites + 7, // Main panel sprites + 16, // Main strings + // ITE specific resources + 0, // Actor names + 0, // Default portraits + // IHNM specific resources + 11, // Option panel sprites + 12, // Warning panel + 13, // Warning panel sprites + 15 // Psychic profile background }; static const GameFontDescription ITEDEMO_GameFonts[] = { {0}, {1} }; @@ -102,14 +112,14 @@ static const GameFontDescription IHNMDEMO_GameFonts[] = { {2}, {3}, {4} }; // Font 6 is kIHNMFont8, font 8 is kIHNMMainFont static const GameFontDescription IHNMCD_GameFonts[] = { {2}, {3}, {4}, {5}, {6}, {7}, {8} }; -// frequency, sampleBits, stereo, isBigEndian, isSigned -static const GameSoundInfo ITEPC_GameSound = { kSoundPCM, 22050, 16, false, false, true }; -static const GameSoundInfo ITEWINDEMO1_GameSound = { kSoundPCM, 22050, 8, false, false, false }; -static const GameSoundInfo ITEMACCD_G_GameSound = { kSoundMacPCM, 22050, 8, false, false, false }; -static const GameSoundInfo ITEDISK_GameSound = { kSoundVOC, -1, -1, false, false, true }; -static const GameSoundInfo ITEDEMO_GameVoice = { kSoundVOX, 22050, 16, false, false, true }; -static const GameSoundInfo IHNM_GameSound = { kSoundWAV, -1, -1, false, false, true }; -static const GameSoundInfo MAC_GameSound = { kSoundPCM, 22050, 16, false, true, true }; +// sampleBits, isBigEndian, isSigned +static const GameSoundInfo ITEPC_GameSound = { kSoundPCM, 16, false, true }; +static const GameSoundInfo ITEWINDEMO1_GameSound = { kSoundPCM, 8, false, false }; +static const GameSoundInfo ITEMACCD_G_GameSound = { kSoundMacPCM, 8, false, false }; +static const GameSoundInfo ITEDISK_GameSound = { kSoundVOC, -1, false, true }; +static const GameSoundInfo ITEDEMO_GameVoice = { kSoundVOX, 16, false, true }; +static const GameSoundInfo IHNM_GameSound = { kSoundWAV, -1, false, true }; +static const GameSoundInfo MAC_GameSound = { kSoundPCM, 16, true, true }; // Patch files. Files not found will be ignored static const GamePatchDescription ITEPatch_Files[] = { diff --git a/engines/saga/gfx.cpp b/engines/saga/gfx.cpp index d1f592e38b..85416991db 100644 --- a/engines/saga/gfx.cpp +++ b/engines/saga/gfx.cpp @@ -28,7 +28,6 @@ #include "saga/saga.h" #include "saga/gfx.h" #include "saga/interface.h" -#include "saga/sagaresnames.h" #include "saga/rscfile.h" #include "saga/scene.h" @@ -37,6 +36,9 @@ namespace Saga { +#define RID_IHNM_DEFAULT_PALETTE 1 +#define RID_IHNM_HOURGLASS_CURSOR 11 // not in demo + Gfx::Gfx(SagaEngine *vm, OSystem *system, int width, int height) : _vm(vm), _system(system) { _system->beginGFXTransaction(); _vm->initCommonGFX(width > 320); diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index ef31b85156..7380570a99 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -43,7 +43,6 @@ #include "saga/sound.h" #include "saga/sprite.h" #include "saga/rscfile.h" -#include "saga/sagaresnames.h" #include "saga/interface.h" @@ -327,6 +326,9 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { _statusTextInputState = kStatusTextInputFirstRun; _disableAbortSpeeches = false; + + // set save game reminder alarm + _vm->_timer->installTimerProc(&saveReminderCallback, TIMETOSAVE, this); } Interface::~Interface(void) { @@ -337,6 +339,22 @@ Interface::~Interface(void) { _scenePortraits.freeMem(); } +void Interface::saveReminderCallback(void *refCon) { + ((Interface *)refCon)->updateSaveReminder(); +} + +void Interface::updateSaveReminder() { + // TODO: finish this + /* + if (_active && _panelMode == kPanelMain) { + _vm->_timer->removeTimerProc(&saveReminderCallback); + _saveReminderState = (_saveReminderState == 0) ? 1 : 0; + drawStatusBar(); + _vm->_timer->installTimerProc(&saveReminderCallback, TIMETOSAVE, this); + } + */ +} + int Interface::activate() { if (!_active) { _active = true; @@ -477,9 +495,9 @@ void Interface::setMode(int mode) { bool Interface::processAscii(Common::KeyState keystate) { // TODO: Checking for Esc and Enter below is a bit hackish, and - // and probably only works with the English version. Maybe we should - // add a flag to the button so it can indicate if it's the default or - // cancel button? + // probably only works with the English version. Maybe we should + // add a flag to the button so it can indicate if it's the default + // or cancel button? uint16 ascii = keystate.ascii; int i; PanelButton *panelButton; @@ -2755,7 +2773,7 @@ void Interface::mapPanelDrawCrossHair() { if (screen.contains(mapPosition)) { _vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _vm->_sprite->_mainSprites, - _mapPanelCrossHairState? RID_ITE_SPR_XHAIR1 : RID_ITE_SPR_XHAIR2, + _mapPanelCrossHairState? RID_ITE_SPR_CROSSHAIR : RID_ITE_SPR_CROSSHAIR + 1, mapPosition, 256); } } diff --git a/engines/saga/interface.h b/engines/saga/interface.h index af59fe64d2..2091c9f071 100644 --- a/engines/saga/interface.h +++ b/engines/saga/interface.h @@ -56,6 +56,12 @@ enum InterfaceUpdateFlags { #define STATUS_TEXT_LEN 128 #define STATUS_TEXT_INPUT_MAX 256 +#define RID_IHNM_BOSS_SCREEN 19 // not in demo +#define RID_ITE_TYCHO_MAP 1686 +#define RID_ITE_SPR_CROSSHAIR (73 + 9) +#define TIMETOSAVE (kScriptTimeTicksPerSecond * 1000 * 60 * 30) +#define TIMETOBLINK (kScriptTimeTicksPerSecond * 1000 * 1) + // Converse-specific stuff enum PanelModes { @@ -233,6 +239,9 @@ public: void disableAbortSpeeches(bool d) { _disableAbortSpeeches = d; } + static void saveReminderCallback(void *refCon); + void updateSaveReminder(); + bool _textInput; bool _statusTextInput; diff --git a/engines/saga/ihnm_introproc.cpp b/engines/saga/introproc_ihnm.cpp index 5f1d0157d5..5f1d0157d5 100644 --- a/engines/saga/ihnm_introproc.cpp +++ b/engines/saga/introproc_ihnm.cpp diff --git a/engines/saga/ite_introproc.cpp b/engines/saga/introproc_ite.cpp index 2aa263b097..a33a55c375 100644 --- a/engines/saga/ite_introproc.cpp +++ b/engines/saga/introproc_ite.cpp @@ -36,7 +36,6 @@ #include "saga/music.h" #include "saga/scene.h" -#include "saga/sagaresnames.h" #include "saga/rscfile.h" namespace Saga { @@ -46,6 +45,21 @@ using Common::EN_ANY; using Common::DE_DEU; using Common::IT_ITA; +// Intro scenes +#define RID_ITE_INTRO_ANIM_SCENE 1538 +#define RID_ITE_CAVE_SCENE_1 1542 +#define RID_ITE_CAVE_SCENE_2 1545 +#define RID_ITE_CAVE_SCENE_3 1548 +#define RID_ITE_CAVE_SCENE_4 1551 +#define RID_ITE_VALLEY_SCENE 1556 +#define RID_ITE_TREEHOUSE_SCENE 1560 +#define RID_ITE_FAIREPATH_SCENE 1564 +#define RID_ITE_FAIRETENT_SCENE 1567 + +// ITE intro music +#define MUSIC_1 9 +#define MUSIC_2 10 + LoadSceneParams ITE_IntroList[] = { {RID_ITE_INTRO_ANIM_SCENE, kLoadByResourceId, NULL, Scene::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, {RID_ITE_CAVE_SCENE_1, kLoadByResourceId, NULL, Scene::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE}, @@ -380,63 +394,65 @@ int Scene::ITEIntroCave1Proc(int param) { static const IntroDialogue dialogue[][4] = { { { // English - RID_CAVE_VOICE_0, + 0, // cave voice 0 "We see the sky, we see the land, we see the water, " "and we wonder: Are we the only ones?" }, { - RID_CAVE_VOICE_1, + 1, // cave voice 1 "Long before we came to exist, the humans ruled the " "Earth." }, { - RID_CAVE_VOICE_2, + 2, // cave voice 2 "They made marvelous things, and moved whole " "mountains." }, { - RID_CAVE_VOICE_3, + 3, // cave voice 3 "They knew the Secret of Flight, the Secret of " "Happiness, and other secrets beyond our imagining." } }, + // ----------------------------------------------------- { { // German - RID_CAVE_VOICE_0, + 0, // cave voice 0 "Um uns sind der Himmel, das Land und die Seen; und " "wir fragen uns - sind wir die einzigen?" }, { - RID_CAVE_VOICE_1, + 1, // cave voice 1 "Lange vor unserer Zeit herrschten die Menschen " "\201ber die Erde." }, { - RID_CAVE_VOICE_2, + 2, // cave voice 2 "Sie taten wundersame Dinge und versetzten ganze " "Berge." }, { - RID_CAVE_VOICE_3, + 3, // cave voice 3 "Sie kannten das Geheimnis des Fluges, das Geheimnis " "der Fr\224hlichkeit und andere Geheimnisse, die " "unsere Vorstellungskraft \201bersteigen." } }, + // ----------------------------------------------------- { { // Italian fan translation - RID_CAVE_VOICE_0, + 0, // cave voice 0 "Guardiamo il cielo, guardiamo la terra, guardiamo " "l'acqua, e ci chiediamo: Siamo forse soli?" }, { - RID_CAVE_VOICE_1, + 1, // cave voice 1 "Molto tempo prima che noi esistessimo, gli Umani " "dominavano la terra." }, { - RID_CAVE_VOICE_2, + 2, // cave voice 2 "Fecero cose meravigliose, e mossero intere " "montagne." }, { - RID_CAVE_VOICE_3, + 3, // cave voice 3 "Conoscevano il Segreto del Volo, il Segreto della " "Felicit\224, ed altri segreti oltre ogni nostra " "immaginazione." @@ -493,47 +509,49 @@ int Scene::ITEIntroCave2Proc(int param) { static const IntroDialogue dialogue[][3] = { { { // English - RID_CAVE_VOICE_4, + 4, // cave voice 4 "The humans also knew the Secret of Life, and they " "used it to give us the Four Great Gifts:" }, { - RID_CAVE_VOICE_5, + 5, // cave voice 5 "Thinking minds, feeling hearts, speaking mouths, and " "reaching hands." }, { - RID_CAVE_VOICE_6, + 6, // cave voice 6 "We are their children." } }, + // ----------------------------------------------------- { { // German - RID_CAVE_VOICE_4, + 4, // cave voice 4 "Au$erdem kannten die Menschen das Geheimnis des " "Lebens. Und sie nutzten es, um uns die vier gro$en " "Geschenke zu geben -" }, { - RID_CAVE_VOICE_5, + 5, // cave voice 5 "den denkenden Geist, das f\201hlende Herz, den " "sprechenden Mund und die greifende Hand." }, { - RID_CAVE_VOICE_6, + 6, // cave voice 6 "Wir sind ihre Kinder." } }, + // ----------------------------------------------------- { { // Italian fan translation - RID_CAVE_VOICE_4, + 4, // cave voice 4 "Gli Umani conoscevano anche il Segreto della Vita, " "e lo usarono per darci i Quattro Grandi Doni:" }, { - RID_CAVE_VOICE_5, + 5, // cave voice 5 "Il pensiero, le emozioni, la parola e la manualit\224." }, { - RID_CAVE_VOICE_6, + 6, // cave voice 6 "Siamo i loro figli." } } }; @@ -595,46 +613,48 @@ int Scene::ITEIntroCave3Proc(int param) { static const IntroDialogue dialogue[][3] = { { { // English - RID_CAVE_VOICE_7, + 7, // cave voice 7 "They taught us how to use our hands, and how to " "speak." }, { - RID_CAVE_VOICE_8, + 8, // cave voice 8 "They showed us the joy of using our minds." }, { - RID_CAVE_VOICE_9, + 9, // cave voice 9 "They loved us, and when we were ready, they surely " "would have given us the Secret of Happiness." } }, + // ----------------------------------------------------- { { // German - RID_CAVE_VOICE_7, + 7, // cave voice 7 "Sie lehrten uns zu sprechen und unsere H\204nde zu " "benutzen." }, { - RID_CAVE_VOICE_8, + 8, // cave voice 8 "Sie zeigten uns die Freude am Denken." }, { - RID_CAVE_VOICE_9, + 9, // cave voice 9 "Sie liebten uns, und w\204ren wir bereit gewesen, " "h\204tten sie uns sicherlich das Geheimnis der " "Fr\224hlichkeit offenbart." } }, + // ----------------------------------------------------- { { // Italian fan translation - RID_CAVE_VOICE_7, + 7, // cave voice 7 "Ci insegnarono come usare le mani e come parlare. " }, { - RID_CAVE_VOICE_8, + 8, // cave voice 8 "Ci mostrarono le gioie che l'uso della mente " "pu\242 dare. " }, { - RID_CAVE_VOICE_9, + 9, // cave voice 9 "Ci amarono, ed una volta pronti, ci avrebbero " "sicuramente svelato il Segreto della Felicit\224." @@ -698,60 +718,62 @@ int Scene::ITEIntroCave4Proc(int param) { static const IntroDialogue dialogue[][4] = { { { // English - RID_CAVE_VOICE_10, + 10, // cave voice 10 "And now we see the sky, the land, and the water that " "we are heirs to, and we wonder: why did they leave?" }, { - RID_CAVE_VOICE_11, + 11, // cave voice 11 "Do they live still, in the stars? In the oceans " "depths? In the wind?" }, { - RID_CAVE_VOICE_12, + 12, // cave voice 12 "We wonder, was their fate good or evil?" }, { - RID_CAVE_VOICE_13, + 13, // cave voice 13 "And will we also share the same fate one day?" } }, + // ----------------------------------------------------- { { // German - RID_CAVE_VOICE_10, + 10, // cave voice 10 "Und nun sehen wir den Himmel, das Land und die " "Seen - unser Erbe. Und wir fragen uns - warum " "verschwanden sie?" }, { - RID_CAVE_VOICE_11, + 11, // cave voice 11 "Leben sie noch in den Sternen? In den Tiefen des " "Ozeans? Im Wind?" }, { - RID_CAVE_VOICE_12, + 12, // cave voice 12 "Wir fragen uns - war ihr Schicksal gut oder b\224se?" }, { - RID_CAVE_VOICE_13, + 13, // cave voice 13 "Und wird uns eines Tages das gleiche Schicksal " "ereilen?" } }, + // ----------------------------------------------------- { { // Italian fan translation - RID_CAVE_VOICE_10, + 10, // cave voice 10 "Ed ora che guardiamo il cielo, la terra e l'acqua " "che abbiamo ereditato, pensiamo: Perch\233 partirono?" }, { - RID_CAVE_VOICE_11, + 11, // cave voice 11 "Vivono ancora, nelle stelle? Nelle profondit\224 " "dell'oceano? Nel vento?" }, { - RID_CAVE_VOICE_12, + 12, // cave voice 12 "Ci domandiamo, il loro destino fu felice o nefasto?" }, { - RID_CAVE_VOICE_13, + 13, // cave voice 13 "E un giorno, condivideremo anche noi lo stesso " "destino?" } } diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp index 7a6d6a4398..e607adb4cb 100644 --- a/engines/saga/isomap.cpp +++ b/engines/saga/isomap.cpp @@ -27,7 +27,6 @@ #include "saga/saga.h" #include "saga/gfx.h" -#include "saga/sagaresnames.h" #include "saga/scene.h" #include "saga/isomap.h" @@ -285,7 +284,7 @@ void IsoMap::adjustScroll(bool jump) { tileCoordsToScreenPoint(_vm->_actor->_centerActor->_location, playerPoint); - if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) { + if (_vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP) { _mapPosition.x = (playerPoint.x + _viewScroll.x) * 30 / 100 - (381); _mapPosition.y = (playerPoint.y + _viewScroll.y) * 30 / 100 - (342); } @@ -322,7 +321,7 @@ void IsoMap::adjustScroll(bool jump) { _viewScroll.x = smoothSlide( _viewScroll.x, minScrollPos.x, maxScrollPos.x ); } - if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) { + if (_vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP) { ObjectData *obj; uint16 objectId; objectId = _vm->_actor->objIndexToId(ITE_OBJ_MAP); @@ -1510,7 +1509,7 @@ void IsoMap::findTilePath(ActorData* actor, const Location &start, const Locatio memset( &_searchArray, 0, sizeof(_searchArray)); if (!(actor->_actorFlags & kActorNoCollide) && - (_vm->_scene->currentSceneResourceId() != RID_ITE_OVERMAP_SCENE)) { + (_vm->_scene->currentSceneResourceId() != ITE_SCENE_OVERMAP)) { for (i = 0; i < _vm->_actor->_actorsCount; i++) { other = _vm->_actor->_actors[i]; if (!other->_inScene) continue; @@ -1664,7 +1663,7 @@ void IsoMap::screenPointToTileCoords(const Point &position, Location &location) Point mPos(position); int x,y; - if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE){ + if (_vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP){ if (mPos.y < 16) { mPos.y = 16; } diff --git a/engines/saga/isomap.h b/engines/saga/isomap.h index c79ae7cd0a..eb548ce5dc 100644 --- a/engines/saga/isomap.h +++ b/engines/saga/isomap.h @@ -32,6 +32,8 @@ namespace Saga { +#define ITE_OBJ_MAP 14 + #define SAGA_ISOTILEDATA_LEN 8 #define SAGA_ISOTILE_WIDTH 32 #define SAGA_ISOTILE_BASEHEIGHT 15 diff --git a/engines/saga/itedata.cpp b/engines/saga/itedata.cpp index 1274f72b45..43c3d21012 100644 --- a/engines/saga/itedata.cpp +++ b/engines/saga/itedata.cpp @@ -26,7 +26,6 @@ // Actor and Object data tables #include "saga/saga.h" #include "saga/itedata.h" -#include "saga/sagaresnames.h" #include "saga/sndres.h" namespace Saga { @@ -245,7 +244,7 @@ ObjectTableData ITE_ObjectTable[ITE_OBJECTCOUNT] = { { 23, 0, 480, 480, 0, 24, 23, 0 }, // Silver Medallion { 24, 0, 480, 480, 0, 25, 24, 0 }, // Mud in Fur { 25, 0, 480, 480, 0, 26, 25, 0 }, // Gold Ring - { 27, 13, 1036, 572, 40, 47, 14, kObjUseWith }, // Screwdriver + { 27, 13, 1036, 572, 40, 47, 14, kObjUseWith }, // Screwdriver { 28, 0, 480, 480, 0, 29, 26, 0 }, // Apple Token { 29, 0, 480, 480, 0, 30, 22, kObjUseWith }, // Letter from Elara { 30, 0, 164, 440, 0, 31, 16, kObjUseWith }, // Spoon @@ -258,82 +257,86 @@ ObjectTableData ITE_ObjectTable[ITE_OBJECTCOUNT] = { { 40, 269, 644, 416, 0, 41, 39, kObjNotFlat }, // Electrical Cable { 41, 12, 280, 516, 0, 43, 17, kObjUseWith }, // Piece of flint { 42, 5, 876, 332, 32, 65, 18, 0 }, // Rat Cloak - { 43, 52, 556, 1612, 0, 49, 28, kObjUseWith | kObjNotFlat }, // Bucket + { 43, 52, 556, 1612, 0, 49, 28, kObjUseWith | + kObjNotFlat }, // Bucket { 48, 52, 732, 948, 0, 50, 27, kObjUseWith }, // Cup { 49, 52, 520, 1872, 0, 53, 29, 0 }, // Fertilizer { 50, 52, 1012, 1268, 0, 52, 30, 0 }, // Feeder - { 51, 252, -20, -20, 0, 71, 32, kObjUseWith | kObjNotFlat }, // Bowl in jail cell + { 51, 252, -20, -20, 0, 71, 32, kObjUseWith | + kObjNotFlat }, // Bowl in jail cell { 53, 252, 1148, 388, 0, 70, 33, 0 }, // Loose stone block in jail cell { 26, 12, 496, 368, 0, 76, 31, 0 }, // Coil of Rope from Quarry { 54, 281, 620, 352, 0, 80, 46, 0 } // Orb of Storms in Dam Lab }; FxTable ITE_SfxTable[ITE_SFXCOUNT] = { - { FX_DOOR_OPEN, 127 }, - { FX_DOOR_CLOSE, 127 }, - { FX_RUSH_WATER, 63 }, // Floppy volume: 127 - { FX_RUSH_WATER, 26 }, // Floppy volume: 40 - { FX_CRICKET, 64 }, - { FX_PORTICULLIS, 84 }, // Floppy volume: 127 - { FX_CLOCK_1, 64 }, - { FX_CLOCK_2, 64 }, - { FX_DAM_MACHINE, 64 }, - { FX_DAM_MACHINE, 40 }, - { FX_HUM1, 64 }, - { FX_HUM2, 64 }, - { FX_HUM3, 64 }, - { FX_HUM4, 64 }, - { FX_WATER_LOOP_S, 32 }, // Floppy volume: 64 - { FX_SURF, 42 }, // Floppy volume: 127 - { FX_SURF, 32 }, // Floppy volume: 64 - { FX_FIRELOOP, 64 }, // Floppy volume: 96 - { FX_SCRAPING, 84 }, // Floppy volume: 127 - { FX_BEE_SWARM, 64 }, // Floppy volume: 96 - { FX_BEE_SWARM, 26 }, // Floppy volume: 40 - { FX_SQUEAKBOARD, 64 }, - { FX_KNOCK, 127 }, - { FX_COINS, 32 }, // Floppy volume: 48 - { FX_STORM, 84 }, // Floppy volume: 127 - { FX_DOOR_CLOSE_2, 84 }, // Floppy volume: 127 - { FX_ARCWELD, 84 }, // Floppy volume: 127 - { FX_RETRACT_ORB, 127 }, - { FX_DRAGON, 127 }, - { FX_SNORES, 127 }, - { FX_SPLASH, 127 }, - { FX_LOBBY_DOOR, 127 }, - { FX_CHIRP_LOOP, 26 }, // Floppy volume: 40 - { FX_DOOR_CREAK, 96 }, - { FX_SPOON_DIG, 64 }, - { FX_CROW, 96 }, - { FX_COLDWIND, 42 }, // Floppy volume: 64 - { FX_TOOL_SND_1, 96 }, - { FX_TOOL_SND_2, 127 }, - { FX_TOOL_SND_3, 64 }, - { FX_DOOR_METAL, 96 }, - { FX_WATER_LOOP_S, 32 }, - { FX_WATER_LOOP_L, 32 }, // Floppy volume: 64 - { FX_DOOR_OPEN_2, 127 }, - { FX_JAIL_DOOR, 64 }, - { FX_KILN_FIRE, 53 }, // Floppy volume: 80 - - // Only in the CD version - { FX_CROWD_01, 64 }, - { FX_CROWD_02, 64 }, - { FX_CROWD_03, 64 }, - { FX_CROWD_04, 64 }, - { FX_CROWD_05, 64 }, - { FX_CROWD_06, 64 }, - { FX_CROWD_07, 64 }, - { FX_CROWD_08, 64 }, - { FX_CROWD_09, 64 }, - { FX_CROWD_10, 64 }, - { FX_CROWD_11, 64 }, - { FX_CROWD_12, 64 }, - { FX_CROWD_13, 64 }, - { FX_CROWD_14, 64 }, - { FX_CROWD_15, 64 }, - { FX_CROWD_16, 64 }, - { FX_CROWD_17, 64 } + { 14, 127 }, // Door open + { 15, 127 }, // Door close + { 16, 63 }, // Rush water (floppy volume: 127) + { 16, 26 }, // Rush water (floppy volume: 40) + { 17, 64 }, // Cricket + { 18, 84 }, // Porticullis (floppy volume: 127) + { 19, 64 }, // Clock 1 + { 20, 64 }, // Clock 2 + { 21, 64 }, // Dam machine + { 21, 40 }, // Dam machine + { 22, 64 }, // Hum 1 + { 23, 64 }, // Hum 2 + { 24, 64 }, // Hum 3 + { 25, 64 }, // Hum 4 + // Note: the following effect was set to 51 for + // some unknown reason + { 26, 32 }, // Stream + { 27, 42 }, // Surf (floppy volume: 127) + { 27, 32 }, // Surf (floppy volume: 64) + { 28, 64 }, // Fire loop (floppy volume: 96) + { 29, 84 }, // Scraping (floppy volume: 127) + { 30, 64 }, // Bee swarm (floppy volume: 96) + { 30, 26 }, // Bee swarm (floppy volume: 40) + { 31, 64 }, // Squeaky board + { 32, 127 }, // Knock + { 33, 32 }, // Coins (floppy volume: 48) + { 34, 84 }, // Storm (floppy volume: 127) + { 35, 84 }, // Door close 2 (floppy volume: 127) + { 36, 84 }, // Arcweld (floppy volume: 127) + { 37, 127 }, // Retract orb + { 38, 127 }, // Dragon + { 39, 127 }, // Snores + { 40, 127 }, // Splash + { 41, 127 }, // Lobby door + { 42, 26 }, // Chirp loop (floppy volume: 40) + { 43, 96 }, // Door creak + { 44, 64 }, // Spoon dig + { 45, 96 }, // Crow + { 46, 42 }, // Cold wind (floppy volume: 64) + { 47, 96 }, // Tool sound 1 + { 48, 127 }, // Tool sound 2 + { 49, 64 }, // Tool sound 3 + { 50, 96 }, // Metal door + { 51, 32 }, // Water loop S + { 52, 32 }, // Water loop L (floppy volume: 64) + { 53, 127 }, // Door open 2 + { 54, 64 }, // Jail door + { 55, 53 }, // Killing fire (floppy volume: 80) + //{ 56, 0 }, // Dummy FX + // Crowd effects, which exist only in the CD version + { 57, 64 }, + { 58, 64 }, + { 59, 64 }, + { 60, 64 }, + { 61, 64 }, + { 62, 64 }, + { 63, 64 }, + { 64, 64 }, + { 65, 64 }, + { 66, 64 }, + { 67, 64 }, + { 68, 64 }, + { 69, 64 }, + { 70, 64 }, + { 71, 64 }, + { 72, 64 }, + { 73, 64 } }; const char *ITEinterfaceTextStrings[][52] = { @@ -493,14 +496,6 @@ const char *solicitStr[][NUM_SOLICIT_REPLIES] = { } }; -const char portraitList[] = { - RID_ITE_JFERRET_SERIOUS, - RID_ITE_JFERRET_GOOFY, - RID_ITE_JFERRET_SERIOUS, - RID_ITE_JFERRET_GOOFY, - RID_ITE_JFERRET_ALOOF -}; - const char *sakkaStr[][NUM_SAKKA] = { { "Hey, you're not supposed to help the applicants!", "Guys! This is supposed to be a test!", diff --git a/engines/saga/module.mk b/engines/saga/module.mk index 76783a17ae..b1929361a2 100644 --- a/engines/saga/module.mk +++ b/engines/saga/module.mk @@ -11,11 +11,11 @@ MODULE_OBJS := \ font.o \ font_map.o \ gfx.o \ - ihnm_introproc.o \ image.o \ interface.o \ + introproc_ihnm.o \ + introproc_ite.o \ isomap.o \ - ite_introproc.o \ itedata.o \ objectmap.o \ puzzle.o \ diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 1cbc38dfb5..732bd0b50c 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -28,7 +28,6 @@ #include "saga/saga.h" #include "saga/rscfile.h" -#include "saga/sagaresnames.h" #include "saga/music.h" #include "sound/audiostream.h" @@ -40,6 +39,7 @@ namespace Saga { #define BUFFER_SIZE 4096 +#define MUSIC_SUNSPOT 26 class DigitalMusicInputStream : public Audio::AudioStream { private: @@ -58,6 +58,7 @@ private: const int16 *_pos; const GameSoundInfo *_musicInfo; MemoryReadStream *_memoryStream; + SagaEngine *_vm; void refill(); bool eosIntern() const { @@ -73,18 +74,21 @@ public: int readBuffer(int16 *buffer, const int numSamples); bool endOfData() const { return eosIntern(); } - bool isStereo() const { return _musicInfo->stereo; } - int getRate() const { return _musicInfo->frequency; } + bool isStereo() const { + // The digital music in the ITE Mac demo version is not stereo + return _vm->getGameId() == GID_ITE_MACDEMO2 ? false : true; + } + int getRate() const { return 11025; } }; DigitalMusicInputStream::DigitalMusicInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping, uint32 loopStart) - : _context(context), _finished(false), _looping(looping), _bufferEnd(_buf + BUFFER_SIZE) { + : _vm(vm), _context(context), _finished(false), _looping(looping), _bufferEnd(_buf + BUFFER_SIZE) { byte compressedHeader[10]; - resourceData = vm->_resource->getResourceData(context, resourceId); + resourceData = _vm->_resource->getResourceData(context, resourceId); _file = context->getFile(resourceData); - _musicInfo = vm->getMusicInfo(); + _musicInfo = _vm->getMusicInfo(); if (_musicInfo == NULL) { error("DigitalMusicInputStream() wrong musicInfo"); @@ -480,7 +484,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) { if (_digitalMusicContext != NULL) { //TODO: check resource size loopStart = 0; - // fix ITE sunstatm score + // fix ITE sunstatm/sunspot score if ((_vm->getGameType() == GType_ITE) && (resourceId == MUSIC_SUNSPOT)) { loopStart = 4 * 18727; } @@ -557,7 +561,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) { musicFile.read(resourceData, resourceSize); musicFile.close(); - // TODO: The Mac music format is unknown (probably TFMX?) + // TODO: The Mac music format is unsupported (QuickTime MIDI) // so stop here return; } else { diff --git a/engines/saga/palanim.cpp b/engines/saga/palanim.cpp index c5129fcf06..319946f2d5 100644 --- a/engines/saga/palanim.cpp +++ b/engines/saga/palanim.cpp @@ -66,12 +66,7 @@ int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) { debug(3, "PalAnim::loadPalAnim(): Loading %d PALANIM entries.", _entryCount); - test_p = calloc(_entryCount, sizeof(PalanimEntry)); - if (test_p == NULL) { - warning("PalAnim::loadPalAnim(): Allocation failure"); - return MEM; - } - + test_p = malloc(_entryCount * sizeof(PalanimEntry)); _entries = (PalanimEntry *)test_p; for (i = 0; i < _entryCount; i++) { @@ -87,22 +82,12 @@ int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) { debug(2, "PalAnim::loadPalAnim(): Entry %d: Loading %d palette indices.\n", i, pal_count); - test_p = calloc(1, sizeof(char) * pal_count); - if (test_p == NULL) { - warning("PalAnim::loadPalAnim(): Allocation failure"); - return MEM; - } - + test_p = malloc(sizeof(char) * pal_count); _entries[i].pal_index = (byte *)test_p; debug(2, "PalAnim::loadPalAnim(): Entry %d: Loading %d SAGA_COLOR structures.", i, color_count); - test_p = calloc(1, sizeof(Color) * color_count); - if (test_p == NULL) { - warning("PalAnim::loadPalAnim(): Allocation failure"); - return MEM; - } - + test_p = malloc(sizeof(Color) * color_count); _entries[i].colors = (Color *)test_p; for (p = 0; p < pal_count; p++) { diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp index 23eaa42531..2835775320 100644 --- a/engines/saga/puzzle.cpp +++ b/engines/saga/puzzle.cpp @@ -31,13 +31,14 @@ #include "saga/sprite.h" #include "saga/puzzle.h" #include "saga/render.h" -#include "saga/sagaresnames.h" #include "common/system.h" #include "common/timer.h" namespace Saga { +#define ITE_ACTOR_PUZZLE 176 + #define PUZZLE_X_OFFSET 72 #define PUZZLE_Y_OFFSET 46 @@ -45,6 +46,21 @@ namespace Saga { #define PUZZLE_MOVED 0x04 // 1 when somewhere in the box #define PUZZLE_ALL_SET PUZZLE_FIT | PUZZLE_MOVED +// Puzzle portraits +#define RID_ITE_SAKKA_APPRAISING 6 +#define RID_ITE_SAKKA_DENIAL 7 +#define RID_ITE_SAKKA_EXCITED 8 +#define RID_ITE_JFERRET_SERIOUS 9 +#define RID_ITE_JFERRET_GOOFY 10 +#define RID_ITE_JFERRET_ALOOF 11 + +const char portraitList[] = { + RID_ITE_JFERRET_SERIOUS, + RID_ITE_JFERRET_GOOFY, + RID_ITE_JFERRET_SERIOUS, + RID_ITE_JFERRET_GOOFY, + RID_ITE_JFERRET_ALOOF +}; enum rifOptions { kROLater = 0, @@ -54,7 +70,12 @@ enum rifOptions { }; Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) { - _lang = (_vm->getLanguage() == Common::DE_DEU) ? 1 : 0; + _lang = 0; + + if (_vm->getLanguage() == Common::DE_DEU) + _lang = 1; + else if (_vm->getLanguage() == Common::IT_ITA) + _lang = 2; _hintRqState = kRQNoHint; _hintOffer = 0; diff --git a/engines/saga/rscfile.cpp b/engines/saga/rscfile.cpp index bd5bfdfa1d..b7d4f4f1bd 100644 --- a/engines/saga/rscfile.cpp +++ b/engines/saga/rscfile.cpp @@ -658,12 +658,8 @@ static int metaResourceTable[] = { 0, 326, 517, 677, 805, 968, 1165, 0, 1271 }; static int metaResourceTableDemo[] = { 0, 0, 0, 0, 0, 0, 0, 285, 0 }; void Resource::loadGlobalResources(int chapter, int actorsEntrance) { - if (chapter < 0) { - if (_vm->getGameId() != GID_IHNM_DEMO) - chapter = 8; - else - chapter = 7; - } + if (chapter < 0) + chapter = (_vm->getGameId() != GID_IHNM_DEMO) ? 8 : 7; // TODO //if (module.voiceLUT) diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index 8200526ecf..40eb32b276 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -53,7 +53,6 @@ #include "saga/music.h" #include "saga/palanim.h" #include "saga/objectmap.h" -#include "saga/sagaresnames.h" namespace Saga { @@ -251,7 +250,7 @@ int SagaEngine::go() { _scene->changeScene(ConfMan.getInt("start_scene"), 0, kTransitionNoFade); } else if (ConfMan.hasKey("boot_param")) { if (getGameType() == GType_ITE) - _interface->addToInventory(_actor->objIndexToId(ITE_OBJ_MAGIC_HAT)); + _interface->addToInventory(_actor->objIndexToId(0)); // Magic hat _scene->changeScene(ConfMan.getInt("boot_param"), 0, kTransitionNoFade); } else if (ConfMan.hasKey("save_slot")) { // First scene sets up palette @@ -421,25 +420,25 @@ const char *SagaEngine::getTextString(int textStringId) { void SagaEngine::getExcuseInfo(int verb, const char *&textString, int &soundResourceId) { textString = NULL; - if (verb == _script->getVerbType(kVerbPickUp)) { - textString = getTextString(kTextICantPickup); - soundResourceId = RID_BOAR_VOICE_007; - } else - if (verb == _script->getVerbType(kVerbLookAt)) { - textString = getTextString(kTextNothingSpecial); - soundResourceId = RID_BOAR_VOICE_006; - } - if (verb == _script->getVerbType(kVerbOpen)) { + if (verb == _script->getVerbType(kVerbOpen)) { textString = getTextString(kTextNoPlaceToOpen); - soundResourceId = RID_BOAR_VOICE_000; - } - if (verb == _script->getVerbType(kVerbClose)) { + soundResourceId = 239; // Boar voice 0 + } + if (verb == _script->getVerbType(kVerbClose)) { textString = getTextString(kTextNoOpening); - soundResourceId = RID_BOAR_VOICE_002; - } - if (verb == _script->getVerbType(kVerbUse)) { + soundResourceId = 241; // Boar voice 2 + } + if (verb == _script->getVerbType(kVerbUse)) { textString = getTextString(kTextDontKnow); - soundResourceId = RID_BOAR_VOICE_005; + soundResourceId = 244; // Boar voice 5 + } + if (verb == _script->getVerbType(kVerbLookAt)) { + textString = getTextString(kTextNothingSpecial); + soundResourceId = 245; // Boar voice 6 + } + if (verb == _script->getVerbType(kVerbPickUp)) { + textString = getTextString(kTextICantPickup); + soundResourceId = 246; // Boar voice 7 } } diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 35c3736b31..4a5fae7ddb 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -82,11 +82,11 @@ using Common::MemoryReadStreamEndian; #define OBJECT_TYPE_MASK ((1 << OBJECT_TYPE_SHIFT) - 1) #define OBJ_SPRITE_BASE 9 +#define IHNM_OBJ_PROFILE 0x4000 #define memoryError(Place) error("%s Memory allocation error.", Place) enum ERRORCODE { - MEM = -2,//todo: remove FAILURE = -1, SUCCESS = 0 }; @@ -303,15 +303,17 @@ struct GameResourceDescription { uint32 mainPanelResourceId; uint32 conversePanelResourceId; uint32 optionPanelResourceId; - uint32 warningPanelResourceId; - uint32 warningPanelSpritesResourceId; uint32 mainSpritesResourceId; uint32 mainPanelSpritesResourceId; - uint32 optionPanelSpritesResourceId; - uint32 defaultPortraitsResourceId; - uint32 psychicProfileResourceId; uint32 mainStringsResourceId; + // ITE specific resources uint32 actorsStringsResourceId; + uint32 defaultPortraitsResourceId; + // IHNM specific resources + uint32 optionPanelSpritesResourceId; + uint32 warningPanelResourceId; + uint32 warningPanelSpritesResourceId; + uint32 psychicProfileResourceId; }; struct GameFontDescription { @@ -322,9 +324,7 @@ struct GameDisplayInfo; struct GameSoundInfo { GameSoundTypes resourceType; - long frequency; int sampleBits; - bool stereo; bool isBigEndian; bool isSigned; }; @@ -580,15 +580,15 @@ public: _mouseClickCount = 0; } - const bool leftMouseButtonPressed() const { + bool leftMouseButtonPressed() const { return _leftMouseButtonPressed; } - const bool rightMouseButtonPressed() const { + bool rightMouseButtonPressed() const { return _rightMouseButtonPressed; } - const bool mouseButtonPressed() const { + bool mouseButtonPressed() const { return _leftMouseButtonPressed || _rightMouseButtonPressed; } @@ -622,8 +622,8 @@ public: public: bool initGame(void); - const bool isBigEndian() const; - const bool isMacResources() const; + bool isBigEndian() const; + bool isMacResources() const; const GameResourceDescription *getResourceDescription(); const GameSoundInfo *getVoiceInfo() const; const GameSoundInfo *getSfxInfo() const; diff --git a/engines/saga/sagaresnames.h b/engines/saga/sagaresnames.h deleted file mode 100644 index 5bce483c3e..0000000000 --- a/engines/saga/sagaresnames.h +++ /dev/null @@ -1,274 +0,0 @@ -/* 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 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$ - * - */ - -// Descriptive names for game resource numbers - -#ifndef SAGA_RESOURCENAMES_H -#define SAGA_RESOURCENAMES_H - -namespace Saga { - -// Prefix RID_ means Resource Id - -// Lookup tables -#define RID_ITE_SCENE_LUT 1806 -#define RID_ITE_SCRIPT_LUT 216 - -#define RID_ITEDEMO_SCENE_LUT 318 -#define RID_ITEDEMO_SCRIPT_LUT 146 - -#define RID_IHNM_SCENE_LUT 1272 -#define RID_IHNM_SCRIPT_LUT 29 -#define RID_IHNM_SFX_LUT 265 - -#define RID_IHNMDEMO_SCENE_LUT 286 -#define RID_IHNMDEMO_SCRIPT_LUT 18 -#define RID_IHNMDEMO_SFX_LUT 222 - -// Object names -#define ITE_OBJ_MAP 14 -#define ITE_OBJ_MAGIC_HAT 0 - -#define IHNM_OBJ_PROFILE 0x4000 - -#define RID_IHNM_DEFAULT_PALETTE 1 - -// Actor names -#define ITE_ACTOR_PUZZLE 176 - -// Scenes -#define ITE_SCENE_INV -1 -#define ITE_SCENE_PUZZLE 26 -#define ITE_SCENE_LODGE 21 -#define ITE_SCENE_ENDCREDIT1 295 - -#define ITE_DEFAULT_SCENE 32 -#define IHNM_DEFAULT_SCENE 151 - -#define ITEDEMO_DEFAULT_SCENE 68 -#define IHNMDEMO_DEFAULT_SCENE 144 - -// Fonts -#define RID_MEDIUM_FONT 0 -#define RID_BIG_FONT 1 -#define RID_SMALL_FONT 2 - -// Interface images -#define RID_ITE_MAIN_PANEL 3 -#define RID_ITE_CONVERSE_PANEL 4 -#define RID_ITE_OPTION_PANEL 5 -#define RID_ITE_MAIN_SPRITES 6 -#define RID_ITE_MAIN_PANEL_SPRITES 7 -#define RID_ITE_MAIN_STRINGS 35 //main strings -#define RID_ITE_ACTOR_NAMES 36 //actors names -#define RID_ITE_DEFAULT_PORTRAITS 125 - -#define RID_ITEDEMO_MAIN_PANEL 2 -#define RID_ITEDEMO_CONVERSE_PANEL 3 -#define RID_ITEDEMO_OPTION_PANEL 3 // FIXME: should be 4 but it is an empty resource. -#define RID_ITEDEMO_MAIN_SPRITES 5 // Proper fix would be not load options panel when demo is running -#define RID_ITEDEMO_MAIN_PANEL_SPRITES 6 -#define RID_ITEDEMO_MAIN_STRINGS 8 //main strings -#define RID_ITEDEMO_ACTOR_NAMES 9 //actors names -#define RID_ITEDEMO_DEFAULT_PORTRAITS 80 - -#define RID_ITE_TYCHO_MAP 1686 -#define RID_ITE_SPR_XHAIR1 (73 + 9) -#define RID_ITE_SPR_XHAIR2 (74 + 9) - -#define RID_IHNM_MAIN_PANEL 9 -#define RID_IHNM_CONVERSE_PANEL 10 -#define RID_IHNM_HOURGLASS_CURSOR 11 -#define RID_IHNM_MAIN_SPRITES 12 -#define RID_IHNM_MAIN_PANEL_SPRITES 12 -#define RID_IHNM_ARROW_SPRITES 13 -#define RID_IHNM_SAVEREMINDER_SPRITES 14 -#define RID_IHNM_OPTION_PANEL 15 -#define RID_IHNM_OPTION_PANEL_SPRITES 16 -#define RID_IHNM_WARNING_PANEL 17 -#define RID_IHNM_WARNING_PANEL_SPRITES 18 -#define RID_IHNM_BOSS_SCREEN 19 -#define RID_IHNM_PROFILE_BG 20 -#define RID_IHNM_MAIN_STRINGS 21 - -#define RID_IHNMDEMO_MAIN_PANEL 5 -#define RID_IHNMDEMO_CONVERSE_PANEL 6 -#define RID_IHNMDEMO_HOURGLASS_CURSOR 6 // Does not exist in the demo -#define RID_IHNMDEMO_MAIN_SPRITES 7 -#define RID_IHNMDEMO_MAIN_PANEL_SPRITES 7 -#define RID_IHNMDEMO_ARROW_SPRITES 8 -#define RID_IHNMDEMO_SAVEREMINDER_SPRITES 9 -#define RID_IHNMDEMO_OPTION_PANEL 10 -#define RID_IHNMDEMO_OPTION_PANEL_SPRITES 11 -#define RID_IHNMDEMO_WARNING_PANEL 12 -#define RID_IHNMDEMO_WARNING_PANEL_SPRITES 13 -#define RID_IHNMDEMO_BOSS_SCREEN 14 // Does not exist in the demo -#define RID_IHNMDEMO_PROFILE_BG 15 -#define RID_IHNMDEMO_MAIN_STRINGS 16 - -// Puzzle portraits -#define RID_ITE_SAKKA_APPRAISING 6 -#define RID_ITE_SAKKA_DENIAL 7 -#define RID_ITE_SAKKA_EXCITED 8 -#define RID_ITE_JFERRET_SERIOUS 9 -#define RID_ITE_JFERRET_GOOFY 10 -#define RID_ITE_JFERRET_ALOOF 11 - -// ITE Scene resource numbers -#define RID_ITE_OVERMAP_SCENE 226 -#define RID_ITE_INTRO_ANIM_SCENE 1538 -#define RID_ITE_CAVE_SCENE_1 1542 -#define RID_ITE_CAVE_SCENE_2 1545 -#define RID_ITE_CAVE_SCENE_3 1548 -#define RID_ITE_CAVE_SCENE_4 1551 - -#define RID_ITE_VALLEY_SCENE 1556 -#define RID_ITE_TREEHOUSE_SCENE 1560 -#define RID_ITE_FAIREPATH_SCENE 1564 -#define RID_ITE_FAIRETENT_SCENE 1567 - -#define RID_ITE_INTRO_ANIM_STARTFRAME 1529 - -#define RID_ITE_INTRO_ANIM_1 1530 -#define RID_ITE_INTRO_ANIM_2 1531 -#define RID_ITE_INTRO_ANIM_3 1532 -#define RID_ITE_INTRO_ANIM_4 1533 -#define RID_ITE_INTRO_ANIM_5 1534 -#define RID_ITE_INTRO_ANIM_6 1535 -#define RID_ITE_INTRO_ANIM_7 1536 - -#define RID_ITE_CAVE_IMG_1 1540 -#define RID_ITE_CAVE_IMG_2 1543 -#define RID_ITE_CAVE_IMG_3 1546 -#define RID_ITE_CAVE_IMG_4 1549 - -#define RID_ITE_INTRO_IMG_1 1552 -#define RID_ITE_INTRO_IMG_2 1557 -#define RID_ITE_INTRO_IMG_3 1561 -#define RID_ITE_INTRO_IMG_4 1565 - -// ITE voices -#define RID_CAVE_VOICE_0 0 -#define RID_CAVE_VOICE_1 1 -#define RID_CAVE_VOICE_2 2 -#define RID_CAVE_VOICE_3 3 -#define RID_CAVE_VOICE_4 4 -#define RID_CAVE_VOICE_5 5 -#define RID_CAVE_VOICE_6 6 -#define RID_CAVE_VOICE_7 7 -#define RID_CAVE_VOICE_8 8 -#define RID_CAVE_VOICE_9 9 -#define RID_CAVE_VOICE_10 10 -#define RID_CAVE_VOICE_11 11 -#define RID_CAVE_VOICE_12 12 -#define RID_CAVE_VOICE_13 13 - -#define RID_SCENE1_VOICE_009 57 -//TODO: fill it -#define RID_SCENE1_VOICE_138 186 - -#define RID_BOAR_VOICE_000 239 -#define RID_BOAR_VOICE_002 241 -#define RID_BOAR_VOICE_005 244 -#define RID_BOAR_VOICE_006 245 -#define RID_BOAR_VOICE_007 246 - -// Music -#define MUSIC_1 9 -#define MUSIC_2 10 -#define MUSIC_SUNSPOT 26 - -// TODO: If the sound effects are numbered sequentially, we don't really need -// these constants. But for now they might be useful for debugging. - -// Sound effects - -#define FX_DOOR_OPEN 14 -#define FX_DOOR_CLOSE 15 -#define FX_RUSH_WATER 16 -#define FX_CRICKET 17 -#define FX_PORTICULLIS 18 -#define FX_CLOCK_1 19 -#define FX_CLOCK_2 20 -#define FX_DAM_MACHINE 21 -#define FX_HUM1 22 -#define FX_HUM2 23 -#define FX_HUM3 24 -#define FX_HUM4 25 -#define FX_STREAM 26 -#define FX_SURF 27 -#define FX_FIRELOOP 28 -#define FX_SCRAPING 29 -#define FX_BEE_SWARM 30 -#define FX_SQUEAKBOARD 31 -#define FX_KNOCK 32 -#define FX_COINS 33 -#define FX_STORM 34 -#define FX_DOOR_CLOSE_2 35 -#define FX_ARCWELD 36 -#define FX_RETRACT_ORB 37 -#define FX_DRAGON 38 -#define FX_SNORES 39 -#define FX_SPLASH 40 -#define FX_LOBBY_DOOR 41 -#define FX_CHIRP_LOOP 42 -#define FX_DOOR_CREAK 43 -#define FX_SPOON_DIG 44 -#define FX_CROW 45 -#define FX_COLDWIND 46 -#define FX_TOOL_SND_1 47 -#define FX_TOOL_SND_2 48 -#define FX_TOOL_SND_3 49 -#define FX_DOOR_METAL 50 -#define FX_WATER_LOOP_S 51 -#define FX_WATER_LOOP_L 52 -#define FX_DOOR_OPEN_2 53 -#define FX_JAIL_DOOR 54 -#define FX_KILN_FIRE 55 -#define FX_DUMMY 56 - -// These are only in the CD version - -#define FX_CROWD_01 57 -#define FX_CROWD_02 58 -#define FX_CROWD_03 59 -#define FX_CROWD_04 60 -#define FX_CROWD_05 61 -#define FX_CROWD_06 62 -#define FX_CROWD_07 63 -#define FX_CROWD_08 64 -#define FX_CROWD_09 65 -#define FX_CROWD_10 66 -#define FX_CROWD_11 67 -#define FX_CROWD_12 68 -#define FX_CROWD_13 69 -#define FX_CROWD_14 70 -#define FX_CROWD_15 71 -#define FX_CROWD_16 72 -#define FX_CROWD_17 73 - -} // End of namespace Saga - -#endif diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp index 53290cbc5d..8d00f9d2d0 100644 --- a/engines/saga/saveload.cpp +++ b/engines/saga/saveload.cpp @@ -37,7 +37,6 @@ #include "saga/isomap.h" #include "saga/music.h" #include "saga/render.h" -#include "saga/sagaresnames.h" #include "saga/scene.h" #include "saga/script.h" diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 4520c3f406..c3c1587822 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -43,7 +43,6 @@ #include "saga/scene.h" #include "saga/actor.h" #include "saga/rscfile.h" -#include "saga/sagaresnames.h" #include "graphics/iff.h" #include "common/util.h" diff --git a/engines/saga/scene.h b/engines/saga/scene.h index 0e4c0ed66a..723792f050 100644 --- a/engines/saga/scene.h +++ b/engines/saga/scene.h @@ -38,9 +38,21 @@ namespace Saga { //#define SCENE_DEBUG // for scene debugging #define SCENE_DOORS_MAX 16 - #define NO_CHAPTER_CHANGE -2 +// Scenes +#define ITE_SCENE_INV -1 +#define ITE_SCENE_PUZZLE 26 +#define ITE_SCENE_LODGE 21 +#define ITE_SCENE_ENDCREDIT1 295 +#define ITE_SCENE_OVERMAP 226 + +// Default scenes +#define ITE_DEFAULT_SCENE 32 +#define IHNM_DEFAULT_SCENE 151 +#define ITEDEMO_DEFAULT_SCENE 68 +#define IHNMDEMO_DEFAULT_SCENE 144 + class ObjectMap; struct Event; diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index 4862ce3be0..ea61f5ce04 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -47,7 +47,6 @@ #include "saga/scene.h" #include "saga/isomap.h" -#include "saga/sagaresnames.h" #include "common/config-manager.h" diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index 9d3d4a9afa..8d269fb3e8 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -28,7 +28,6 @@ #include "saga/saga.h" #include "saga/itedata.h" -#include "saga/sagaresnames.h" #include "saga/rscfile.h" #include "saga/sndres.h" #include "saga/sound.h" @@ -43,6 +42,9 @@ namespace Saga { +#define RID_IHNM_SFX_LUT 265 +#define RID_IHNMDEMO_SFX_LUT 222 + SndRes::SndRes(SagaEngine *vm) : _vm(vm) { // Load sound module resource file contexts _sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE); @@ -259,11 +261,11 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff switch (resourceType) { case kSoundPCM: - buffer.frequency = soundInfo->frequency; + buffer.frequency = 22050; buffer.isSigned = soundInfo->isSigned; buffer.sampleBits = soundInfo->sampleBits; buffer.size = soundResourceLength; - buffer.stereo = soundInfo->stereo; + buffer.stereo = false; if (onlyHeader) { buffer.buffer = NULL; free(soundResource); @@ -273,11 +275,11 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff result = true; break; case kSoundMacPCM: - buffer.frequency = soundInfo->frequency; + buffer.frequency = 22050; buffer.isSigned = soundInfo->isSigned; buffer.sampleBits = soundInfo->sampleBits; buffer.size = soundResourceLength - 36; - buffer.stereo = soundInfo->stereo; + buffer.stereo = false; if (onlyHeader) { buffer.buffer = NULL; } else { @@ -288,10 +290,10 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff result = true; break; case kSoundVOX: - buffer.frequency = soundInfo->frequency; + buffer.frequency = 22050; buffer.isSigned = soundInfo->isSigned; buffer.sampleBits = soundInfo->sampleBits; - buffer.stereo = soundInfo->stereo; + buffer.stereo = false; buffer.size = soundResourceLength * 4; if (onlyHeader) { buffer.buffer = NULL; diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp index b5c675a403..e9d002819c 100644 --- a/engines/saga/sprite.cpp +++ b/engines/saga/sprite.cpp @@ -29,7 +29,6 @@ #include "saga/gfx.h" #include "saga/scene.h" -#include "saga/sagaresnames.h" #include "saga/rscfile.h" #include "saga/font.h" @@ -37,6 +36,11 @@ namespace Saga { +#define RID_IHNM_ARROW_SPRITES 13 +#define RID_IHNM_SAVEREMINDER_SPRITES 14 +#define RID_IHNMDEMO_ARROW_SPRITES 8 +#define RID_IHNMDEMO_SAVEREMINDER_SPRITES 9 + Sprite::Sprite(SagaEngine *vm) : _vm(vm) { debug(8, "Initializing sprite subsystem..."); diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp index bc18632659..c1b289a060 100644 --- a/engines/saga/sthread.cpp +++ b/engines/saga/sthread.cpp @@ -34,10 +34,12 @@ #include "saga/script.h" #include "saga/scene.h" -#include "saga/sagaresnames.h" namespace Saga { +#define RID_SCENE1_VOICE_START 57 +#define RID_SCENE1_VOICE_END 186 + ScriptThread *Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber) { ScriptThread *newThread; @@ -653,8 +655,8 @@ bool Script::runThread(ScriptThread *thread, uint instructionLimit) { if (_vm->getGameId() == GID_ITE_DISK_G) { // special ITE dos if ((_vm->_scene->currentSceneNumber() == ITE_DEFAULT_SCENE) && - (iparam1 >= 288) && (iparam1 <= (RID_SCENE1_VOICE_138 - RID_SCENE1_VOICE_009 + 288))) { - sampleResourceId = RID_SCENE1_VOICE_009 + iparam1 - 288; + (iparam1 >= 288) && (iparam1 <= (RID_SCENE1_VOICE_END - RID_SCENE1_VOICE_START + 288))) { + sampleResourceId = RID_SCENE1_VOICE_START + iparam1 - 288; } } else { if (thread->_voiceLUT->voicesCount > first) { diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 46d034d880..8f3175f098 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -371,7 +371,7 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) { break; } } else { - if (chr == '@' && _vm->_language != Common::ZH_TWN) + if (chr == '@' && !(_vm->_game.id == GID_CMI && _vm->_language == Common::ZH_TWN)) continue; if (chr == 255 || (_vm->_game.version <= 6 && chr == 254)) { chr = text[pos++]; @@ -400,7 +400,8 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) { // Some localizations may override colors // See credits in Chinese COMI - if (chr == '^' && pos == 1) { + if (_vm->_game.id == GID_CMI && _vm->_language == Common::ZH_TWN && + chr == '^' && pos == 1) { if (text[pos] == 'c') { pos += 4; chr = text[pos++]; diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index 954e400c2c..9f9115e207 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -498,25 +498,24 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) { } bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { - Common::Array<Common::EngineDebugLevel> lvls = Common::listSpecialDebugLevels(); + const Common::DebugLevelContainer &lvls = Common::listSpecialDebugLevels(); bool setFlag = false; // Remove or add debug channel? if ((argc == 1) && (Common::getEnabledSpecialDebugLevels() == 0)) { DebugPrintf("No debug flags are enabled\n"); DebugPrintf("Available Channels: "); - for (uint i = 0; i < lvls.size(); i++) { - DebugPrintf("%s, ", lvls[i].option.c_str()); + for (Common::DebugLevelContainer::iterator i = lvls.begin(); i != lvls.end(); ++i) { + DebugPrintf("%s, ", i->option.c_str()); } DebugPrintf("\n"); return true; } if ((argc == 1) && (Common::getEnabledSpecialDebugLevels() > 0)) { - for (uint i = 0; i < lvls.size(); i++) { - if (lvls[i].enabled) - DebugPrintf("%s - %s\n", lvls[i].option.c_str(), - lvls[i].description.c_str()); + for (Common::DebugLevelContainer::iterator i = lvls.begin(); i != lvls.end(); ++i) { + if (i->enabled) + DebugPrintf("%s - %s\n", i->option.c_str(), i->description.c_str()); } return true; } @@ -529,25 +528,24 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { } else { DebugPrintf("Syntax: Debug +CHANNEL, or Debug -CHANNEL\n"); DebugPrintf("Available Channels: "); - for (uint i = 0; i < lvls.size(); i++) { - DebugPrintf("%s, ", lvls[i].option.c_str()); - DebugPrintf("\n"); + for (Common::DebugLevelContainer::iterator i = lvls.begin(); i != lvls.end(); ++i) { + DebugPrintf("%s\n", i->option.c_str()); } } // Identify flag const char *realFlag = argv[1] + 1; - for (uint i = 0; i < lvls.size(); i++) { - if ((scumm_stricmp(lvls[i].option.c_str(), realFlag)) == 0) { + for (Common::DebugLevelContainer::iterator i = lvls.begin(); i != lvls.end(); ++i) { + if (i->option.equalsIgnoreCase(realFlag)) { if (setFlag) { - enableSpecialDebugLevel(lvls[i].option); + enableSpecialDebugLevel(i->option); DebugPrintf("Enable "); } else { - disableSpecialDebugLevel(lvls[i].option); + disableSpecialDebugLevel(i->option); DebugPrintf("Disable "); } - DebugPrintf("%s\n", lvls[i].description.c_str()); + DebugPrintf("%s\n", i->description.c_str()); return true; } } diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 18d51e133d..324cc91e78 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -89,7 +89,8 @@ static const PlainGameDescriptor gameDescriptions[] = { { "baseball2001", "Backyard Baseball 2001" }, { "Baseball2003", "Backyard Baseball 2003" }, { "basketball", "Backyard Basketball" }, - { "BluesABCTime", "Blue's ABC Time" }, + { "Blues123Time", "Blue's 123 Time Activities" }, + { "BluesABCTime", "Blue's ABC Time Activities" }, { "BluesBirthday", "Blue's Birthday Adventure" }, { "catalog", "Humongous Interactive Catalog" }, { "chase", "SPY Fox in Cheese Chase" }, @@ -116,7 +117,7 @@ static const PlainGameDescriptor gameDescriptions[] = { { "PuttsFunShop", "Putt-Putt's One-Stop Fun Shop" }, { "putttime", "Putt-Putt Travels Through Time" }, { "puttzoo", "Putt-Putt Saves the Zoo" }, - { "readdemo", "Blue's Reading Time Activities (Demo)" }, + { "readtime", "Blue's Reading Time Activities" }, { "SamsFunShop", "Pajama Sam's One-Stop Fun Shop" }, { "soccer", "Backyard Soccer" }, { "Soccer2004", "Backyard Soccer 2004" }, @@ -285,8 +286,7 @@ static const GameSettings gameVariantsTable[] = { {"dog", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, {"maze", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, - {"water", "", 0, GID_WATER, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, - {"water", "HE 99", 0, GID_WATER, 6, 99, MDT_NONE, GF_USE_KEY, UNK}, + {"water", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, // condMaskCode value changed in setUserCondition & setTalkCondition {"putttime", "", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK}, @@ -319,6 +319,7 @@ static const GameSettings gameVariantsTable[] = { {"soccer", "", 0, GID_SOCCER, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, // Global scripts increased to 2048 + {"blues123time", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK}, {"freddi4", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK}, {"freddi4", "unenc", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_HE_985, UNK}, @@ -353,7 +354,7 @@ static const GameSettings gameVariantsTable[] = { // Uses smacker in external files, for testing only {"arttime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, - {"readdemo", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, + {"readtime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, {"football2002", 0, 0, GID_FOOTBALL, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, @@ -511,6 +512,9 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "basketball", "basketball", kGenHEPC, UNK_LANG, UNK, 0 }, { "basketball", "Basketball", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, + { "blues123time", "Blues123time", kGenHEPC, UNK_LANG, UNK, 0 }, + { "blues123time", "Blue's 123 Time", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, + { "bluesabctime", "bluesabctime", kGenHEPC, UNK_LANG, UNK, 0 }, { "bluesabctime", "BluesABCTimeDemo", kGenHEPC, UNK_LANG, UNK, 0 }, { "bluesabctime", "BluesABCTimeDemo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, @@ -550,6 +554,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "freddi", "freddi", kGenHEPC, UNK_LANG, UNK, 0 }, { "freddi", "Freddi", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, + { "freddi", "Freddi1", kGenHEPC, UNK_LANG, UNK, 0 }, { "freddi", "freddemo", kGenHEPC, UNK_LANG, UNK, 0 }, { "freddi", "Freddi Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "freddi", "Freddi Fish", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, @@ -641,6 +646,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "pajama", "Pajama Sam", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "pajama", "PajamaNHD", kGenHEPC, UNK_LANG, UNK, 0 }, { "pajama", "PJS-DEMO", kGenHEPC, UNK_LANG, UNK, 0 }, + { "pajama", "pjsam", kGenHEPC, UNK_LANG, UNK, 0 }, { "pajama", "PjSamDemo", kGenHEPC, UNK_LANG, UNK, 0 }, { "pajama", "PYJAMA", kGenHEPC, Common::DE_DEU, UNK, 0 }, { "pajama", "SAMDEMO", kGenHEPC, Common::FR_FRA, UNK, 0 }, @@ -750,8 +756,9 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "puttzoo", "zoodemo", kGenHEPC, UNK_LANG, UNK, 0 }, { "puttzoo", "Zoo Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, - { "readdemo", "readDemo", kGenHEPC, UNK_LANG, UNK, 0 }, - { "readdemo", "Blues-ReadingTime Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, + { "readtime", "Blue's Reading Time", kGenHEPC, UNK_LANG, UNK, 0 }, + { "readtime", "readDemo", kGenHEPC, UNK_LANG, UNK, 0 }, + { "readtime", "Blues-ReadingTime Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "SamsFunShop", "SamsFunShop", kGenHEPC, UNK_LANG, UNK, 0 }, { "SamsFunShop", "Sam's FunShop", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 5b6c2bcf35..6d1cf1bbd8 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -692,8 +692,8 @@ void HelpDialog::displayKeyBindings() { _dsc[i]->setLabel(dscStr[i]); } - delete [] keyStr; - delete [] dscStr; + delete[] keyStr; + delete[] dscStr; } void HelpDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp index 71182ca7a0..d56017c6f5 100644 --- a/engines/scumm/nut_renderer.cpp +++ b/engines/scumm/nut_renderer.cpp @@ -41,8 +41,8 @@ NutRenderer::NutRenderer(ScummEngine *vm, const char *filename) : } NutRenderer::~NutRenderer() { - delete [] _charBuffer; - delete [] _decodedData; + delete[] _charBuffer; + delete[] _decodedData; } void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch); @@ -254,14 +254,14 @@ void NutRenderer::loadFont(const char *filename) { offset += (dstPitch * _chars[l].height); } - delete [] _decodedData; + delete[] _decodedData; _decodedData = compressedData; _charBuffer = new byte[_maxCharSize]; } - delete [] dataSrc; - delete [] _paletteMap; + delete[] dataSrc; + delete[] _paletteMap; } int NutRenderer::getCharWidth(byte c) const { diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index a8ef26c484..36b82519e9 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -23,6 +23,8 @@ * */ +#include <time.h> // for ScummEngine::saveInfos / ScummEngine::loadInfos + #include "common/config-manager.h" #include "common/savefile.h" #include "common/system.h" @@ -44,8 +46,6 @@ #include "sound/audiocd.h" #include "sound/mixer.h" -#include <time.h> // for ScummEngine::saveInfos / ScummEngine::loadInfos - namespace Scumm { struct SaveGameHeader { diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp index faae72b6dd..04ea53137b 100644 --- a/engines/scumm/script_v6.cpp +++ b/engines/scumm/script_v6.cpp @@ -23,6 +23,8 @@ * */ +#include <time.h> // for ScummEngine_v6::o6_getDateTime() + #include "common/config-manager.h" #include "common/system.h" @@ -44,8 +46,6 @@ #include "sound/mididrv.h" #include "sound/mixer.h" -#include <time.h> // for ScummEngine_v6::o6_getDateTime() - namespace Scumm { #define OPCODE(x) _OPCODE(ScummEngine_v6, x) diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index ce78e0507a..62d777aa33 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Wed Apr 16 02:07:50 2008 + This file was generated by the md5table tool on Mon Jun 02 08:37:50 2008 DO NOT EDIT MANUALLY! */ @@ -107,6 +107,7 @@ static const MD5Table md5table[] = { { "22c9eb04455440131ffc157aeb8d40a8", "fbear", "HE 70", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, { "22d07d6c386c9c25aca5dac2a0c0d94b", "maniac", "NES", "", 262144, Common::SE_SWE, Common::kPlatformNES }, { "22f4ea88a09da12df9308ba30bcb7d0f", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformPC }, + { "23394c8d29cc63c61313959431a12476", "spyfox", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows }, { "257f8c14d8c584f7ddd601bcb00920c7", "maniac", "NES", "", 262144, Common::DE_DEU, Common::kPlatformNES }, { "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "", "Floppy", 7932, Common::EN_ANY, Common::kPlatformPC }, { "27b3a4224ad63d5b04627595c1c1a025", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformAmiga }, @@ -156,6 +157,7 @@ static const MD5Table md5table[] = { { "39fd6db10d0222d817025c4d3346e3b4", "farm", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "3a03dab514e4038df192d8a8de469788", "atlantis", "", "Floppy", -1, Common::EN_ANY, Common::kPlatformAmiga }, { "3a0c35f3c147b98a2bdf8d400cfc4ab5", "indy3", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, + { "3a3e592b074f595489f7f11e150c398d", "puttzoo", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformWindows }, { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, { "3a5ec90d556d4920976c5578bfbfaf79", "maniac", "NES", "extracted", -1, Common::DE_DEU, Common::kPlatformNES }, { "3af61c5edf8e15b43dbafd285b2e9777", "puttcircus", "", "Demo", -1, Common::HB_ISR, Common::kPlatformWindows }, @@ -285,6 +287,7 @@ static const MD5Table md5table[] = { { "7020931d5a2be0a49d68e7a1882363e4", "zak", "V1", "V1", 1896, Common::EN_ANY, Common::kPlatformPC }, { "70b0719ac3a5b47ae233c561823d5b96", "puttzoo", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh }, { "71523b539491527d9860f4407faf0411", "monkey", "Demo", "EGA Demo", 7607, Common::EN_ANY, Common::kPlatformPC }, + { "71d384e7676c53d513ddd333eae1d82c", "Blues123time", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "71fe97c3108678cf604f14abe342341b", "spyfox2", "", "", -1, Common::NL_NLD, Common::kPlatformWindows }, { "7222f260253f325c21fcfa68b5bfab67", "spyfox2", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "72ac6bc980d5101c2142189d746bd62f", "spyfox", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows }, @@ -300,6 +303,7 @@ static const MD5Table md5table[] = { { "771bc18ec6f93837b839c992b211904b", "monkey", "Demo", "EGA Demo", -1, Common::DE_DEU, Common::kPlatformPC }, { "77f5c9cc0986eb729c1a6b4c8823bbae", "zak", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "780e4a0ae2ff17dc296f4a79543b44f8", "puttmoon", "", "", -1, Common::UNK_LANG, Common::kPlatformPC }, + { "782393c5934ecd0b536eaf5fd541bd26", "pajama", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows }, { "78bd5f036ea35a878b74e4f47941f784", "freddi4", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "78c07ca088526d8d4446a4c2cb501203", "freddi3", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "7974365d3dc0f43a2748c975f91ff042", "monkey2", "", "", -1, Common::ES_ESP, Common::kPlatformPC }, @@ -360,6 +364,7 @@ static const MD5Table md5table[] = { { "92fc0073a4cf259ff36070ecb8628ba8", "thinkerk", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "94aaedbb8f26d71ed3ad6dd34490e29e", "tentacle", "", "Floppy", -1, Common::FR_FRA, Common::kPlatformPC }, { "94db6519da85b8d08c976d8e9a858ea7", "baseball", "HE CUP", "Preview", 10044774, Common::UNK_LANG, Common::kPlatformUnknown }, + { "95818b178d473c989ac753574e8892aa", "readtime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "95b3806e043be08668c54c3ffe98650f", "BluesABCTime", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "96a3069a3c63caa7329588ce1fef41ee", "spyozon", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, { "9708cf716ed8bcc9ff3fcfc69413b746", "puttputt", "HE 61", "", -1, Common::EN_ANY, Common::kPlatformPC }, @@ -388,6 +393,7 @@ static const MD5Table md5table[] = { { "a095e33061606d231ff37dca4c64c8ac", "pajama", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "a0a7dea72003933b8b3f8b99b9f7ddeb", "loom", "No Adlib", "EGA", -1, Common::EN_ANY, Common::kPlatformAtariST }, { "a194f15f51ee62badab74b9e7da97693", "baseball2001", "", "Demo", 20507, Common::EN_ANY, Common::kPlatformUnknown }, + { "a197a87ae77f3b3333f09a7a2c448fe2", "freddi", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows }, { "a28135a7ade38cc0208b04507c46efd1", "spyfox", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "a2bb6aa0537402c1b3c2ea899ccef64b", "lost", "HE 99", "Demo", 15540, Common::EN_ANY, Common::kPlatformWindows }, { "a3036878840720fbefa41e6965fa4a0a", "samnmax", "", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC }, @@ -427,6 +433,7 @@ static const MD5Table md5table[] = { { "bbadf7309c4a2c2763e4bbba3c3be634", "freddi3", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "bc4700bc0e12879f6d25d14d6be6cfdd", "spyfox2", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "bd126753de619a495f9f22adc951c8d5", "monkey2", "", "", -1, Common::IT_ITA, Common::kPlatformPC }, + { "be2abe172f58db170de3a037daa1dd27", "puttputt", "HE 61", "", -1, Common::JA_JPN, Common::kPlatform3DO }, { "be39a5d4db60e8aa736b9086778cb45c", "spyozon", "", "", -1, Common::EN_GRB, Common::kPlatformWindows }, { "be83e882b44f2767bc08d4f766ebc347", "maniac", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformAtariST }, { "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, @@ -471,6 +478,7 @@ static const MD5Table md5table[] = { { "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", -1, Common::DE_DEU, Common::kPlatformWindows }, { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformWindows }, + { "d00ffc8c32d17e575fd985d435d2eb88", "arttime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d0549508a06bbb9f99ed19c9e97891f3", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformPC }, { "d0ad929def3e9cfe39dea55bd12098d4", "puttcircus", "", "", -1, Common::FR_FRA, Common::kPlatformWindows }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index c99856b3a3..2f0593dca8 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -555,8 +555,8 @@ ScummEngine::~ScummEngine() { for (int i = 0; i < _numActors; ++i) delete _actors[i]; - delete [] _actors; - delete [] _sortedActors; + delete[] _actors; + delete[] _sortedActors; delete _2byteFontPtr; delete _charset; @@ -903,7 +903,7 @@ ScummEngine_v8::ScummEngine_v8(OSystem *syst, const DetectorResult &dr) } ScummEngine_v8::~ScummEngine_v8() { - delete [] _objectIDMap; + delete[] _objectIDMap; } #endif diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 26b6aa6e2f..20824ffe74 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -221,7 +221,6 @@ enum ScummGameId { GID_FBEAR, GID_FUNPACK, GID_FREDDI3, - GID_WATER, GID_PUTTRACE, GID_FUNSHOP, // Used for all three funshops GID_FOOTBALL, diff --git a/engines/scumm/smush/channel.cpp b/engines/scumm/smush/channel.cpp index 5b8cd3a853..ccf67764e3 100644 --- a/engines/scumm/smush/channel.cpp +++ b/engines/scumm/smush/channel.cpp @@ -70,7 +70,7 @@ void SmushChannel::processBuffer() { _tbufferSize = 0; } if (_sbufferSize == 0) { - delete []_sbuffer; + delete[] _sbuffer; _sbuffer = 0; } } else { @@ -90,7 +90,7 @@ void SmushChannel::processBuffer() { if (!_sbuffer) error("smush channel failed to allocate memory"); memcpy(_sbuffer, _tbuffer + offset, _sbufferSize); - delete []_tbuffer; + delete[] _tbuffer; _tbuffer = 0; _tbufferSize = 0; } else { @@ -102,7 +102,7 @@ void SmushChannel::processBuffer() { error("smush channel failed to allocate memory"); memcpy(_tbuffer, old + offset, new_size); _tbufferSize = new_size; - delete []old; + delete[] old; } } } diff --git a/engines/scumm/smush/codec37.cpp b/engines/scumm/smush/codec37.cpp index 0c1db13a26..658d67c1b4 100644 --- a/engines/scumm/smush/codec37.cpp +++ b/engines/scumm/smush/codec37.cpp @@ -52,7 +52,7 @@ Codec37Decoder::Codec37Decoder(int width, int height) { Codec37Decoder::~Codec37Decoder() { if (_offsetTable) { - delete []_offsetTable; + delete[] _offsetTable; _offsetTable = 0; _tableLastPitch = -1; _tableLastIndex = -1; diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp index 3a0efbc6b7..822f32a896 100644 --- a/engines/scumm/smush/imuse_channel.cpp +++ b/engines/scumm/smush/imuse_channel.cpp @@ -83,7 +83,7 @@ bool ImuseChannel::appendData(Chunk &b, int32 size) { if (!_tbuffer) error("imuse_channel failed to allocate memory"); memcpy(_tbuffer, old, _tbufferSize); - delete []old; + delete[] old; b.read(_tbuffer + _tbufferSize, size); _tbufferSize += size; } else { @@ -155,7 +155,7 @@ void ImuseChannel::decode() { _tbuffer = new byte[new_size]; if (!_tbuffer) error("imuse_channel failed to allocate memory"); memcpy(_tbuffer, old, _tbufferSize); - delete []old; + delete[] old; memcpy(_tbuffer + _tbufferSize, _sbuffer + _sbufferSize - remaining_size, remaining_size); _tbufferSize += remaining_size; } @@ -180,7 +180,7 @@ void ImuseChannel::decode() { value = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; WRITE_BE_UINT16(decoded, value); decoded += 2; } - delete []_sbuffer; + delete[] _sbuffer; _sbuffer = (byte *)keep; _sbufferSize = new_size; } diff --git a/engines/scumm/smush/saud_channel.cpp b/engines/scumm/smush/saud_channel.cpp index 17296704ea..2fe34efe29 100644 --- a/engines/scumm/smush/saud_channel.cpp +++ b/engines/scumm/smush/saud_channel.cpp @@ -135,7 +135,7 @@ bool SaudChannel::appendData(Chunk &b, int32 size) { if (!_tbuffer) error("saud_channel failed to allocate memory"); memcpy(_tbuffer, old, _tbufferSize); - delete []old; + delete[] old; b.read(_tbuffer + _tbufferSize, size); _tbufferSize += size; } else { diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 906395c0ca..494357a90c 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -86,7 +86,7 @@ public: } ~StringResource() { for (int32 i = 0; i < _nbStrings; i++) { - delete []_strings[i].string; + delete[] _strings[i].string; } } @@ -206,7 +206,7 @@ static StringResource *getStrings(ScummEngine *vm, const char *file, bool is_enc StringResource *sr = new StringResource; assert(sr); sr->init(filebuffer, length); - delete []filebuffer; + delete[] filebuffer; return sr; } diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index f42a803a3d..f039e2ca23 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -174,11 +174,10 @@ void ScummEngine_v6::drawBlastTexts() { // Some localizations may override colors // See credits in Chinese COMI - if (c == '^' && (buf == _blastTextQueue[i].text + 1)) { - int color; - switch (*buf) { - case 'c': - color = buf[3] - '0' + 10 *(buf[2] - '0'); + if (_game.id == GID_CMI && _language == Common::ZH_TWN && + c == '^' && (buf == _blastTextQueue[i].text + 1)) { + if (*buf == 'c') { + int color = buf[3] - '0' + 10 *(buf[2] - '0'); _charset->setColor(color); buf += 4; @@ -1114,7 +1113,8 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize) num += (_game.version == 8) ? 4 : 2; } } else { - if (!(chr == '@' && _game.heversion <= 71) || _language == Common::ZH_TWN) { + if (!(chr == '@' && _game.heversion <= 71) || + (_game.id == GID_CMI && _language == Common::ZH_TWN)) { *dst++ = chr; } } @@ -1462,8 +1462,17 @@ void ScummEngine_v7::translateText(const byte *text, byte *trans_buff) { trans_buff[0] = 0; _lastStringTag[0] = 0; + if (_game.version >= 7 && text[0] == '/') { + // Extract the string tag from the text: /..../ + for (i = 0; (i < 12) && (text[i + 1] != '/'); i++) + _lastStringTag[i] = toupper(text[i + 1]); + _lastStringTag[i] = 0; + } + // WORKAROUND for bug #1172655. if (_game.id == GID_DIG) { + // Based on the second release of The Dig + // Only applies to the subtitles and not speech if (!strcmp((const char *)text, "faint light")) text = (const byte *)"/NEW.007/faint light"; else if (!strcmp((const char *)text, "glowing crystal")) @@ -1488,12 +1497,6 @@ void ScummEngine_v7::translateText(const byte *text, byte *trans_buff) { text = (const byte *)"/NEW.013/unattached lens"; else if (!strcmp((const char *)text, "lens slot")) text = (const byte *)"/NEW.014/lens slot"; - - // Added in second release of The Dig - else if (!strcmp((const char *)text, "/NEWTON.032/")) - text = (const byte *)"/NEW.11/You wish."; - else if (!strcmp((const char *)text, "/NEWTON.034/")) - text = (const byte *)"/NEW.12/In your dreams"; else if (!strcmp((const char *)text, "Jonathon Jackson")) text = (const byte *)"Aram Gutowski"; else if (!strcmp((const char *)text, "Brink")) @@ -1506,8 +1509,8 @@ void ScummEngine_v7::translateText(const byte *text, byte *trans_buff) { if (_game.version >= 7 && text[0] == '/') { // Extract the string tag from the text: /..../ for (i = 0; (i < 12) && (text[i + 1] != '/'); i++) - _lastStringTag[i] = target.tag[i] = toupper(text[i + 1]); - _lastStringTag[i] = target.tag[i] = 0; + target.tag[i] = toupper(text[i + 1]); + target.tag[i] = 0; text += i + 2; // If a language file was loaded, try to find a translated version diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index cf4711f6a2..0a61d10166 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -567,8 +567,8 @@ void ScummEngine::checkExecVerbs() { _mouseAndKeyboardStat = numpad[_mouseAndKeyboardStat - '0']; } - if (_game.platform == Common::kPlatformFMTowns && (_game.id == GID_ZAK || _game.id == GID_INDY3)) { - // HACK: In the FM-Towns games Indy3 and Zak the most significant bit is set for special keys + if (_game.platform == Common::kPlatformFMTowns && _game.version == 3) { + // HACK: In the FM-Towns games Indy3, Loom and Zak the most significant bit is set for special keys // like F5 (=0x8005) or joystick buttons (mask 0xFE00, e.g. SELECT=0xFE40 for the save/load menu). // Hence the distinction with (_mouseAndKeyboardStat < MBS_MAX_KEY) between mouse- and key-events is not applicable // to this games, so we have to remap the special keys here. diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index e53458e33a..d87ed06fef 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -435,6 +435,7 @@ int SkyEngine::init() { SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF; } _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); _floppyIntro = ConfMan.getBool("alt_intro"); diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp index 71e25fc56f..980e0b4f9f 100644 --- a/engines/sword1/control.cpp +++ b/engines/sword1/control.cpp @@ -1225,7 +1225,7 @@ const uint8 Control::_languageStrings[8 * 20][43] = { "Testo", "Fatto", "OK", - "Annula", + "Annulla", "Musica", "Parlato", "Fx", diff --git a/engines/sword2/header.h b/engines/sword2/header.h index 5100e43de1..8cd8c900f8 100644 --- a/engines/sword2/header.h +++ b/engines/sword2/header.h @@ -56,7 +56,7 @@ struct ResHeader { // compressed) byte name[NAME_LEN]; // Name of object - static const int size() { + static int size() { return 44; } @@ -152,7 +152,7 @@ struct AnimHeader { uint8 feetEndDir; // Direction to start in after running anim uint16 blend; - static const int size() { + static int size() { return 15; } @@ -209,7 +209,7 @@ struct CdtEntry { uint8 frameType; // 0 = print sprite normally with top-left // corner at (x,y), otherwise see below... - static const int size() { + static int size() { return 9; } @@ -250,7 +250,7 @@ struct FrameHeader { uint16 width; // Dimensions of frame uint16 height; - static const int size() { + static int size() { return 8; } @@ -299,7 +299,7 @@ struct MultiScreenHeader { uint32 paletteTable; uint32 maskOffset; - static const int size() { + static int size() { return 36; } @@ -339,7 +339,7 @@ struct ScreenHeader { uint16 height; uint16 noLayers; // number of layer areas - static const int size() { + static int size() { return 6; } @@ -374,7 +374,7 @@ struct LayerHeader { uint32 offset; // where to find mask data (from start of // standard file header) - static const int size() { + static int size() { return 16; } @@ -436,7 +436,7 @@ public: _addr = NULL; } - static const int size() { + static int size() { return 44; } @@ -479,7 +479,7 @@ struct TextHeader { uint32 noOfLines; // how many lines of text are there in this // module - static const int size() { + static int size() { return 4; } diff --git a/engines/sword2/mouse.cpp b/engines/sword2/mouse.cpp index 44d2383f78..af4f121e96 100644 --- a/engines/sword2/mouse.cpp +++ b/engines/sword2/mouse.cpp @@ -1462,19 +1462,19 @@ void Mouse::checkPlayerActivity(uint32 seconds) { _vm->_logic->writeVar(RESULT, 0); } -void Mouse::pauseGame() { - // Make the mouse cursor normal. This is the only place where we are - // allowed to clear the luggage this way. +void Mouse::pauseEngine(bool pause) { + if (pause) { + // Make the mouse cursor normal. This is the only place where + // we are allowed to clear the luggage this way. - clearPointerText(); - setLuggageAnim(NULL, 0); - setMouse(0); - setMouseTouching(1); -} - -void Mouse::unpauseGame() { - if (_vm->_logic->readVar(OBJECT_HELD) && _realLuggageItem) - setLuggage(_realLuggageItem); + clearPointerText(); + setLuggageAnim(NULL, 0); + setMouse(0); + setMouseTouching(1); + } else { + if (_vm->_logic->readVar(OBJECT_HELD) && _realLuggageItem) + setLuggage(_realLuggageItem); + } } #define MOUSEFLASHFRAME 6 diff --git a/engines/sword2/mouse.h b/engines/sword2/mouse.h index 09ac9ced20..b87129ac7f 100644 --- a/engines/sword2/mouse.h +++ b/engines/sword2/mouse.h @@ -211,8 +211,7 @@ public: uint32 getMouseTouching() { return _mouseTouching; } void setMouseTouching(uint32 touching) { _mouseTouching = touching; } - void pauseGame(); - void unpauseGame(); + void pauseEngine(bool pause); void setMouse(uint32 res); void setLuggage(uint32 res); diff --git a/engines/sword2/object.h b/engines/sword2/object.h index 57f020eb63..b6b6ca5174 100644 --- a/engines/sword2/object.h +++ b/engines/sword2/object.h @@ -48,7 +48,7 @@ struct ObjectMouse { int32 priority; int32 pointer; // type (or resource id?) of pointer used over this area - static const int size() { + static int size() { return 24; } @@ -91,7 +91,7 @@ public: _addr = addr; } - static const int size() { + static int size() { return 8; } @@ -139,7 +139,7 @@ public: _addr = addr; } - static const int size() { + static int size() { return 12; } @@ -178,7 +178,7 @@ public: _addr = addr; } - static const int size() { + static int size() { return 36; } @@ -240,7 +240,7 @@ public: _addr = addr; } - static const int size() { + static int size() { return 56; } @@ -291,7 +291,7 @@ struct ObjectWalkdata { int32 dx[8 * (12 + 1)]; // walk step distances in x direction int32 dy[8 * (12 + 1)]; // walk step distances in y direction - static const int size() { + static int size() { return 916; } diff --git a/engines/sword2/palette.cpp b/engines/sword2/palette.cpp index 1b9cd28d25..81f93c77ae 100644 --- a/engines/sword2/palette.cpp +++ b/engines/sword2/palette.cpp @@ -156,22 +156,17 @@ void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, ui memcpy(&_palette[4 * startEntry], colourTable, noEntries * 4); if (fadeNow == RDPAL_INSTANT) { - _vm->_system->setPalette(_palette, startEntry, noEntries); + setSystemPalette(_palette, startEntry, noEntries); setNeedFullRedraw(); } } -void Screen::dimPalette() { - byte *p = _palette; - - for (int i = 0; i < 256; i++) { - p[i * 4 + 0] /= 2; - p[i * 4 + 1] /= 2; - p[i * 4 + 2] /= 2; +void Screen::dimPalette(bool dim) { + if (dim != _dimPalette) { + _dimPalette = dim; + setSystemPalette(_palette, 0, 256); + setNeedFullRedraw(); } - - _vm->_system->setPalette(p, 0, 256); - setNeedFullRedraw(); } /** @@ -269,8 +264,24 @@ void Screen::fadeServer() { } } - _vm->_system->setPalette(newPalette, 0, 256); + setSystemPalette(newPalette, 0, 256); setNeedFullRedraw(); } +void Screen::setSystemPalette(const byte *colors, uint start, uint num) { + const byte *palette; + + if (_dimPalette) { + byte pal[256 * 4]; + + for (uint i = start * 4; i < 4 * (start + num); i++) + pal[i] = colors[i] / 2; + + palette = pal; + } else + palette = colors; + + _vm->_system->setPalette(palette, start, num); +} + } // End of namespace Sword2 diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp index 88a1f6251a..d6b8025cda 100644 --- a/engines/sword2/resman.cpp +++ b/engines/sword2/resman.cpp @@ -191,7 +191,7 @@ bool ResourceManager::init() { if (cdInf[i].cd == 0 && !Common::File::exists((char *)cdInf[i].clusterName)) { _vm->GUIErrorMessage("Broken Sword 2: Cannot find " + Common::String((char *)cdInf[i].clusterName)); - delete [] cdInf; + delete[] cdInf; return false; } } @@ -205,7 +205,7 @@ bool ResourceManager::init() { } if (j == _totalClusters) { - delete [] cdInf; + delete[] cdInf; _vm->GUIErrorMessage(Common::String(_resFiles[i].fileName) + " is not in cd.inf"); return false; } @@ -213,7 +213,7 @@ bool ResourceManager::init() { _resFiles[i].cd = cdInf[j].cd; } - delete [] cdInf; + delete[] cdInf; debug(1, "%d resources in %d cluster files", _totalResFiles, _totalClusters); for (i = 0; i < _totalClusters; i++) diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp index 1f6eb1b22d..fdabb3ee6f 100644 --- a/engines/sword2/screen.cpp +++ b/engines/sword2/screen.cpp @@ -97,6 +97,8 @@ Screen::Screen(Sword2Engine *vm, int16 width, int16 height) { _renderAverageTime = 60; _layer = 0; + + _dimPalette = false; } Screen::~Screen() { diff --git a/engines/sword2/screen.h b/engines/sword2/screen.h index d59a6ef3df..6defe51fdc 100644 --- a/engines/sword2/screen.h +++ b/engines/sword2/screen.h @@ -187,7 +187,7 @@ struct Parallax { // The dimensions are followed by an offset table, but we don't know in // advance how big it is. See initializeBackgroundLayer(). - static const int size() { + static int size() { return 4; } @@ -350,6 +350,8 @@ private: uint16 _layer; + bool _dimPalette; + public: Screen(Sword2Engine *vm, int16 width, int16 height); ~Screen(); @@ -400,11 +402,12 @@ public: void setFullPalette(int32 palRes); void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow); + void setSystemPalette(const byte *colors, uint start, uint num); uint8 quickMatch(uint8 r, uint8 g, uint8 b); int32 fadeUp(float time = 0.75); int32 fadeDown(float time = 0.75); uint8 getFadeStatus(); - void dimPalette(); + void dimPalette(bool dim); void waitForFade(); void fadeServer(); diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 0601d11791..7331d1f761 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -225,7 +225,6 @@ Sword2Engine::Sword2Engine(OSystem *syst) : Engine(syst) { #endif _gamePaused = false; - _graphicsLevelFudged = false; _gameCycle = 0; _gameSpeed = 1; @@ -392,7 +391,7 @@ int Sword2Engine::go() { #ifdef SWORD2_DEBUG if (_stepOneCycle) { - pauseGame(); + pauseEngineIntern(true); _stepOneCycle = false; } #endif @@ -406,9 +405,9 @@ int Sword2Engine::go() { switch (ke->kbd.keycode) { case Common::KEYCODE_p: if (_gamePaused) - unpauseGame(); + pauseEngineIntern(false); else - pauseGame(); + pauseEngineIntern(true); break; case Common::KEYCODE_c: if (!_logic->readVar(DEMO) && !_mouse->isChoosing()) { @@ -421,7 +420,7 @@ int Sword2Engine::go() { case Common::KEYCODE_SPACE: if (_gamePaused) { _stepOneCycle = true; - unpauseGame(); + pauseEngineIntern(false); } break; case Common::KEYCODE_s: @@ -689,53 +688,41 @@ void Sword2Engine::sleepUntil(uint32 time) { } } -void Sword2Engine::pauseGame() { - // Don't allow Pause while screen fading or while black - if (_screen->getFadeStatus() != RDFADE_NONE) - return; +void Sword2Engine::pauseEngineIntern(bool pause) { + if (pause) { + // FIXME: We should never disallow pausing, and we need to do + // something about pausing during cutscene moves, credits, etc. - _sound->pauseAllSound(); - _mouse->pauseGame(); + // Don't allow Pause while screen fading or while black + if (_screen->getFadeStatus() != RDFADE_NONE) + return; - // If render level is at max, turn it down because palette-matching - // won't work when the palette is dimmed. - - if (_screen->getRenderLevel() == 3) { - _screen->setRenderLevel(2); - _graphicsLevelFudged = true; - } + _sound->pauseAllSound(); + _mouse->pauseEngine(true); #ifdef SWORD2_DEBUG - // Don't dim it if we're single-stepping through frames - // dim the palette during the pause + // Don't dim it if we're single-stepping through frames + // dim the palette during the pause - if (!_stepOneCycle) - _screen->dimPalette(); + if (!_stepOneCycle) + _screen->dimPalette(true); #else - _screen->dimPalette(); + _screen->dimPalette(true); #endif - _gamePaused = true; -} + _gamePaused = true; + } else { + _mouse->pauseEngine(false); + _sound->unpauseAllSound(); -void Sword2Engine::unpauseGame() { - _mouse->unpauseGame(); - _sound->unpauseAllSound(); + _screen->dimPalette(false); - // Put back game screen palette; see screen.cpp - _screen->setFullPalette(-1); + _gamePaused = false; - // If graphics level at max, turn up again - if (_graphicsLevelFudged) { - _screen->setRenderLevel(3); - _graphicsLevelFudged = false; + // If mouse is about or we're in a chooser menu + if (!_mouse->getMouseStatus() || _mouse->isChoosing()) + _mouse->setMouse(NORMAL_MOUSE_ID); } - - _gamePaused = false; - - // If mouse is about or we're in a chooser menu - if (!_mouse->getMouseStatus() || _mouse->isChoosing()) - _mouse->setMouse(NORMAL_MOUSE_ID); } uint32 Sword2Engine::getMillis() { diff --git a/engines/sword2/sword2.h b/engines/sword2/sword2.h index a9a1e21875..05c5d7fa47 100644 --- a/engines/sword2/sword2.h +++ b/engines/sword2/sword2.h @@ -113,8 +113,7 @@ private: uint32 calcChecksum(byte *buffer, uint32 size); - void pauseGame(); - void unpauseGame(); + virtual void pauseEngineIntern(bool pause); uint32 _totalStartups; uint32 _totalScreenManagers; @@ -208,7 +207,6 @@ public: uint32 findBufferSize(); bool _gamePaused; - bool _graphicsLevelFudged; void startGame(); void gameCycle(); |